Powershell 在生成的文本文件中设置特定行的格式
我想格式化使用Powershell生成的.st(文本)文件中的特定行Powershell 在生成的文本文件中设置特定行的格式,powershell,string-formatting,Powershell,String Formatting,我想格式化使用Powershell生成的.st(文本)文件中的特定行 加载文本片段以供演示使用($TemplateSnippetText) 替换一些文本 将文本行与“:=”对齐,以便所有“:=”都在一行中(作为$TemplateSnippetText) 我正在努力形成,可能是一道数学题。。。? 这可以用String.Format(“{0,6}{1,15})方法完成吗 所需输出 diMoveStep_TFRX := 1;
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
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
实际产出
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
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
完整的Powershell 5.1代码:
$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
我认为您可能使填充过于复杂-根本不需要正则表达式,我们只需要找到初始替换后每行中出现的偏移量
:=
:
$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
如果要保留原始偏移量,只需基于模板计算$targetOffset
,无需进行任何替换,然后再生成实际片段:
$targetOffset = $TemplateSnippetText -replace '\r?\n' |ForEach-Object IndexOf := |Sort-Object -Descending |Select-Object -First 1
$SnippetsToGenerate | ForEach-Object {
# ...
再次感谢Mathias帮我解决这个问题。我还需要做一些改变:
$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"
如果您提供示例输入和所需输出,将帮助我们。simliar是我的第一种方法。但是结构化文本文件似乎是另一种编码的文件。\t 4\s。我如何处理它?@Txitxarro我恐怕不明白您的意思,您可以使用示例吗?VS代码设置:渲染空白选择是«all»。如果我在VSC中打开一个最初使用«b&r automation studio»创建的.st文件,则选项卡不是4个空格,而是“->”变量$TemplateSnippetText中的字符串,我最初从Powershell文件中的.st文件复制的字符串也是->(\t)但您的解决方案中的字符串仅包含空格。但无论如何,将以下内容添加到您的解决方案中可以做到这一点:#输出$lines-替换“”,[char]9-替换“+?(?=:=)’,“非常感谢。我将在星期一对它进行全面测试,然后给你feedback@Txitxarro啊,这很有道理。很高兴听到你解决了问题,不客气!:-)