Reputation: 25
I'm want to format specific Lines in a .st (text) file which was generated with Powershell.
I'm struggling with the formating, probably a math-problem...? Could that be done with the String.Format("{0,6} {1,15}) Method?
Desired Output
diMoveStep_TFRX := 1;
ELSE // Bewegung vorbereiten
diMoveStep_TFRX := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_TFRX OF
0: // Bewegung vorbereiten
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_TFRX := 1;
1: // Bewegung starten
IF stPos.stTFRX.stPickPos1.xEnMove THEN
fbAxis_TFRX.i_stPar.stMove := stMovePar_TFRX;
fbAxis_TFRX.i_stPar.lrPosition := stDataProduct.stTFRX.lrPos_PickPos1;
strPickPos1_TFRX := 'PickPos1';
fbAxis_TFRX.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_TFRX := 2;
END_IF
2: // Bewegung ist gestartet
Actual Output
IF NOT fbAxis_TFRX.i_stCmd.xMoveAbsolute THEN // Bewegung starten
diMoveStep_TFRX := 1;
ELSE // Bewegung vorbereiten
diMoveStep_TFRX := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_TFRX OF
0: // Bewegung vorbereiten
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_TFRX := 1;
1: // Bewegung starten
IF stPos.stTFRX.stPickPos1.xEnMove THEN
fbAxis_TFRX.i_stPar.stMove := stMovePar_TFRX;
fbAxis_TFRX.i_stPar.lrPosition := stDataProduct.stTFRX.lrPos_PickPos1;
strPickPos1_TFRX := 'PickPos1';
fbAxis_TFRX.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_TFRX := 2;
END_IF
2: // Bewegung ist gestartet
Full Powershell 5.1 Code:
$TemplateSnippetText =
"ACTION ActAuto_Move_AXISNAME_TARGETPOS: // COMMENT
// Rücksetzen
IF NOT stStep.xEntryDone THEN
IF NOT fbAxis_AXISNAME.i_stCmd.xMoveAbsolute THEN // Bewegung starten
diMoveStep_AXISNAME := 1;
ELSE // Bewegung vorbereiten
diMoveStep_AXISNAME := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_AXISNAME OF
0: // Bewegung vorbereiten
fbAxis_AXISNAME.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_AXISNAME := 1;
1: // Bewegung starten
IF stPos.stAXISNAME.stTARGETPOS.xEnMove THEN
fbAxis_AXISNAME.i_stPar.stMove := stMovePar_AXISNAME;
fbAxis_AXISNAME.i_stPar.lrPosition := stDataProduct.stAXISNAME.lrPos_TARGETPOS;
strTargetPos_AXISNAME := 'TARGETPOS';
fbAxis_AXISNAME.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_AXISNAME := 2;
END_IF
2: // Bewegung ist gestartet
IF fbAxis_AXISNAME.q_stStat.xMoveDone AND
stPos.stAXISNAME.stTARGETPOS.xInRange THEN
fbAxis_AXISNAME.i_stCmd.xMoveAbsolute := FALSE;
stStep.xActDone := TRUE;
diMoveStep_AXISNAME := 3;
END_IF
3: // Bewegung ist beStringEndt
;
END_CASE
// Stop deaktivieren während der Bewegung
stStep.enStopMode := SEL(fbAxis_AXISNAME.i_stCmd.xMoveAbsolute, EnableStop, DisableStop);
END_ACTION
"
#Dateipfad
$strFilePath = 'C:\Temp\CodeSnippet.st'
$RegPatRepWhiteSpaces = '\s+?(?=:=)' # https://regex101.com/r/IEiymN/1
$RegPatStartOfString = '^.*?(?=:=)' # https://regex101.com/r/icJGAy/1
$RegPatEndOfString = ':=(.*)' # https://regex101.com/r/0UlzT7/1
# File-Inhalt löschen
Remove-Item $strFilePath -Include *.st
$SnippetsToGenerate = @(
[PSCustomObject]@{COMMENT = 'Zielposition1'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos1' }
# [PSCustomObject]@{COMMENT = 'Zielposition2'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos2' }
#[PSCustomObject]@{COMMENT = 'Zielposition3'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos3' }
)
$SnippetsToGenerate | ForEach-Object {
$CurrentSnippet = $TemplateSnippetText
$CurrentSnippet = $CurrentSnippet -replace "COMMENT", $_.COMMENT -replace "AXISNAME", $_.AXISNAME -replace "TARGETPOS", $_.TARGETPOS
$CurrentSnippet | Out-File -FilePath $strFilePath -Append
}
(Get-Content -Path $strFilePath -Raw) -Replace $RegPatRepWhiteSpaces,'' | Set-Content -Path $strFilePath
$IndexOfAllocation = Get-Content -Path $strFilePath | ForEach-Object {$_.IndexOf(":=") } | Measure-Object -Maximum
(Get-Content -Path $strFilePath) | ForEach-Object {
$currentObject = $_
if($currentObject -match ':='){
$StringStart = [Regex]::Matches($currentObject, $RegPatStartOfString).Value
$StringEnd = [Regex]::Matches($currentObject, $RegPatEndOfString ).Value
Write-Host "Lenght StringStart" $StringStart.Length"Lenght StringEnd" $StringEnd.Length
Write-host "Max" $IndexOfAllocation.Maximum
[uint32]$DiffToPaddAbsolute = ($IndexOfAllocation.Maximum - $StringStart.Length)
#if (($DiffToPaddAbsolute % 4) -gt 2) {
$DiffToPaddAbsoluteTabs = [math]::Ceiling($DiffToPaddAbsolute / 4) + 1
# } else {
#$DiffToPaddAbsoluteTabs = [math]::Floor($DiffToPaddAbsolute / 4) + 1
#}
$StringStartPadded= $StringStart.PadRight($StringStart.Length + $DiffToPaddAbsoluteTabs,[char]9)
$currentObject = "$StringStartPadded$StringEnd"
}
$currentObject
} | Set-Content -Path $strFilePath
Invoke-Item $strFilePath
Upvotes: 1
Views: 176
Reputation: 25
Thanks again Mathias for helping me out with this. Had to change a few more things:
$FilePath = "C:\Temp\CodeSnippet.st"
$RegPatRepWhiteSpaces = '\s+?(?=:=)' # https://regex101.com/r/IEiymN/1
[uint16]$SpacesPerTab = 4
$SpacesPerTabAsString = [string]::new([char]32, $SpacesPerTab)
$TemplateSnippetText =
"
ACTION Svd_NAME : // Schutzverdeck: COMMENT
stHw.stBasic.stSvd_AXISNAME.stIn.xProtCircleIsClosedAndLocked := xReplaceMe;
stHw.stBasic.stSvd_AXISNAME.stIn.xAreaRdyForSvd := xRepalaceMe;
fbSvd_AXISNAME.i_stIoMap := stHw.stBasic.stSvd_AXISNAME.stIn;
fbSvd_AXISNAME.i_udiVisu := ADR(stVisu.stBasic.stSvd_AXISNAME);
fbSvd_AXISNAME();
stHw.stBasic.stSvd_AXISNAMEstOut := fbSvd_AXISNAME.q_stIoMap;
xReplaceMe := fbSvd_AXISNAME.q_stStat.xRequest;
END_ACTION
"
$SnippetsToGenerate = @(
[PSCustomObject]@{COMMENT = 'ZielpositionMitEinerLaenge'; AXISNAME = 'LangeraAcnName'; TARGETPOS = 'PickPos1' }
[PSCustomObject]@{COMMENT = 'Zielposition2'; AXISNAME = 'EinNochViiisiiiiiiiiiiiiiielLaengereAchsenName'; TARGETPOS = 'PickPos2' }
[PSCustomObject]@{COMMENT = 'Zielposidaassdtion3'; AXISNAME = 'TFRaaassdX'; TARGETPOS = 'PicdkPos3' }
)
$SnippetsToGenerate | ForEach-Object {
# Use `-creplace` (Case-sensitive replace)
$snippet = $TemplateSnippetText -creplace 'COMMENT', $_.COMMENT -creplace 'AXISNAME', $_.AXISNAME -creplace 'TARGETPOS', $_.TARGETPOS
# Replace all Tabs with Spaces to keep calculation simple
$snippet = $snippet -replace [char]9, $SpacesPerTabAsString -replace $RegPatRepWhiteSpaces, ''
# Split into individual lines
$lines = $snippet -split '\r?\n'
# Use String.IndexOf() to find the current column offset of `:=` in each line
$offsets = $lines | ForEach-Object IndexOf ':='
# Sort the offsets to find the right-most occurrence (we will align everything to this one)
$targetOffset = $offsets | Sort-Object -Descending | Select-Object -First 1
# Round the offset to the next number divisible by SpacesPerTab, then add one more tab
$targetOffset += ($targetOffset % $SpacesPerTab) + $SpacesPerTab
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
$offset = $offsets[$i]
# $offset is > -1, so we know the line contains a `:=`
if ($offset -in 0..$targetOffset) {
# Calculate the number of Spaces that we want to insert
$SpacesToInsert = ($targetOffset - $offset) % $SpacesPerTab
# Calculate the number of Tabs that we want to insert (after filling with Spaces)
$TabsToInsert = ($targetOffset - $offset - $SpacesToInsert) / $SpacesPerTab
# First inserting the required number of spaces at the position right in front of `:=` and after fill up with Tabs
$lines[$i] = $line.Insert($offset, [string]::new(" ", $SpacesToInsert)).Insert($offset + $SpacesToInsert, [string]::new([char]9, $TabsToInsert ))
}
}
# Output, Replace all Groups of Spaces with Tabs
$lines -replace $SpacesPerTabAsString, [char]9
} |Set-Content $FilePath
Invoke-Item "C:\Temp\CodeSnippet.st"
Upvotes: 0
Reputation: 174505
I think you might be over-complicating the padding - regex is not required at all, we just need to find the offset at which :=
occurs in each line after the initial replacement:
$FilePath = "C:\Temp\CodeSnippet.st"
$TemplateSnippetText = "<Insert Your Template Here>"
$SnippetsToGenerate = @(
[PSCustomObject]@{COMMENT = 'Zielposition1'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos1' }
[PSCustomObject]@{COMMENT = 'Zielposition2'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos2' }
[PSCustomObject]@{COMMENT = 'Zielposition3'; AXISNAME = 'TFRX'; TARGETPOS = 'PickPos3' }
)
$SnippetsToGenerate | ForEach-Object {
# Use `-creplace` (Case-sensitive replace)
$snippet = $TemplateSnippetText -creplace 'COMMENT', $_.COMMENT -creplace 'AXISNAME', $_.AXISNAME -creplace 'TARGETPOS', $_.TARGETPOS
# Split into individual lines
$lines = $snippet -split '\r?\n'
# Use String.IndexOf() to find the current column offset of `:=` in each line
$offsets = $lines | ForEach-Object IndexOf ':='
# Sort the offsets to find the right-most occurrence (we will align everything to this one)
$targetOffset = $offsets | Sort-Object -Descending | Select-Object -First 1
for ($i = 0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
$offset = $offsets[$i]
if ($offset -in 0..$targetOffset) {
# $offset is > -1, so we know the line contains a `:=`, let's left-pad it by
# inserting the required number of spaces at the position right in front of `:=`
$lines[$i] = $line.Insert($offset, [string]::new(" ", $targetOffset - $offset))
}
}
# Output
$lines
} |Set-Content $FilePath
Which, with the template provided in your question, gives me the following output in CodeSnippet.st
:
ACTION ActAuto_Move_TFRX_PickPos1: // Zielposition1
// Rücksetzen
IF NOT stStep.xEntryDone THEN
IF NOT fbAxis_TFRX.i_stCmd.xMoveAbsolute THEN // Bewegung starten
diMoveStep_TFRX := 1;
ELSE // Bewegung vorbereiten
diMoveStep_TFRX := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_TFRX OF
0: // Bewegung vorbereiten
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_TFRX := 1;
1: // Bewegung starten
IF stPos.stTFRX.stPickPos1.xEnMove THEN
fbAxis_TFRX.i_stPar.stMove := stMovePar_TFRX;
fbAxis_TFRX.i_stPar.lrPosition := stDataProduct.stTFRX.lrPos_PickPos1;
strTargetPos_TFRX := 'PickPos1';
fbAxis_TFRX.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_TFRX := 2;
END_IF
2: // Bewegung ist gestartet
IF fbAxis_TFRX.q_stStat.xMoveDone AND
stPos.stTFRX.stPickPos1.xInRange THEN
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
stStep.xActDone := TRUE;
diMoveStep_TFRX := 3;
END_IF
3: // Bewegung ist beStringEndt
;
END_CASE
// Stop deaktivieren während der Bewegung
stStep.enStopMode := SEL(fbAxis_TFRX.i_stCmd.xMoveAbsolute, EnableStop, DisableStop);
END_ACTION
ACTION ActAuto_Move_TFRX_PickPos2: // Zielposition2
// Rücksetzen
IF NOT stStep.xEntryDone THEN
IF NOT fbAxis_TFRX.i_stCmd.xMoveAbsolute THEN // Bewegung starten
diMoveStep_TFRX := 1;
ELSE // Bewegung vorbereiten
diMoveStep_TFRX := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_TFRX OF
0: // Bewegung vorbereiten
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_TFRX := 1;
1: // Bewegung starten
IF stPos.stTFRX.stPickPos2.xEnMove THEN
fbAxis_TFRX.i_stPar.stMove := stMovePar_TFRX;
fbAxis_TFRX.i_stPar.lrPosition := stDataProduct.stTFRX.lrPos_PickPos2;
strTargetPos_TFRX := 'PickPos2';
fbAxis_TFRX.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_TFRX := 2;
END_IF
2: // Bewegung ist gestartet
IF fbAxis_TFRX.q_stStat.xMoveDone AND
stPos.stTFRX.stPickPos2.xInRange THEN
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
stStep.xActDone := TRUE;
diMoveStep_TFRX := 3;
END_IF
3: // Bewegung ist beStringEndt
;
END_CASE
// Stop deaktivieren während der Bewegung
stStep.enStopMode := SEL(fbAxis_TFRX.i_stCmd.xMoveAbsolute, EnableStop, DisableStop);
END_ACTION
ACTION ActAuto_Move_TFRX_PickPos3: // Zielposition3
// Rücksetzen
IF NOT stStep.xEntryDone THEN
IF NOT fbAxis_TFRX.i_stCmd.xMoveAbsolute THEN // Bewegung starten
diMoveStep_TFRX := 1;
ELSE // Bewegung vorbereiten
diMoveStep_TFRX := 0;
END_IF
END_IF
// Schrittkette Bewegung
CASE diMoveStep_TFRX OF
0: // Bewegung vorbereiten
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
diMoveStep_TFRX := 1;
1: // Bewegung starten
IF stPos.stTFRX.stPickPos3.xEnMove THEN
fbAxis_TFRX.i_stPar.stMove := stMovePar_TFRX;
fbAxis_TFRX.i_stPar.lrPosition := stDataProduct.stTFRX.lrPos_PickPos3;
strTargetPos_TFRX := 'PickPos3';
fbAxis_TFRX.i_stCmd.xMoveAbsolute := TRUE;
diMoveStep_TFRX := 2;
END_IF
2: // Bewegung ist gestartet
IF fbAxis_TFRX.q_stStat.xMoveDone AND
stPos.stTFRX.stPickPos3.xInRange THEN
fbAxis_TFRX.i_stCmd.xMoveAbsolute := FALSE;
stStep.xActDone := TRUE;
diMoveStep_TFRX := 3;
END_IF
3: // Bewegung ist beStringEndt
;
END_CASE
// Stop deaktivieren während der Bewegung
stStep.enStopMode := SEL(fbAxis_TFRX.i_stCmd.xMoveAbsolute, EnableStop, DisableStop);
END_ACTION
If you want to retain the original offset simply calculate the $targetOffset
based on the template without making any replacements, before generating the actual snippets:
$targetOffset = $TemplateSnippetText -replace '\r?\n' |ForEach-Object IndexOf := |Sort-Object -Descending |Select-Object -First 1
$SnippetsToGenerate | ForEach-Object {
# ...
Upvotes: 1