基于 psobject 更改文本文件中的多行
Changing multiple lines in a text file based on a psobject
我正在编写一个脚本,它将向 txt 文件添加一些附加信息。这些信息存储在 CSV 文件中,如下所示(每次启动脚本时数据都会不同):
Number;A;B;ValueOfB
FP01340/05/20;0;1;GTU_01,GTU_03
FP01342/05/20;1;0;GTU01
txt 文件如下所示(当然每次里面的数据都会不同):
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere|||||
2|zwol|9,00|9,00|0,00
2|23|157,91|194,23|36,32
1|1|FP01341/05/20|2020-05-02|2020-05-02|2020-05-02|12,19|14,99|2,80|Some info |2222222|blabla|11-111 something||||
2|23|12,19|14,99|2,80
1|1|FP01342/05/20|2020-05-02|2020-05-02|2020-05-02|525,36|589,64|64,28|bla|222222|blba 36||62030|something||
2|5|213,93|224,63|10,70
2|8|120,34|129,97|9,63
2|23|191,09|235,04|43,95
我需要做的是找到包含 'Number' 的行,然后从 CSV 中以以下形式添加值 'A' 和 'B':|0|1 然后在下面第一行的末尾,以 |AAA_01、AAA_03
的形式添加 'ValueofB'
所以前两行最后应该是这样的:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere||||||0|1
2|zwol|9,00|9,00|0,00|AAA_01,AAA_03
2|23|157,91|194,23|36,32
其余的行不应该被触及。
我制作了一个脚本,它使用带有上下文的 select-string 方法来查找我需要的内容 - 将其放入一个对象中,然后将我需要的内容添加到之前找到的字符串中,并将其放入一个另一个对象。
我的脚本如下:
$csvFile = Import-Csv -Path Somepath\file.csv -Delimiter ";"
$file = "Somepath2\SomeName.txt"
$LinesToChange = @()
$script:LinesToChange = $LinesToChange
$LinesOriginal = @()
$script:LinesOriginal = $LinesOriginal
foreach ($line in $csvFile) {
Select-String -Path $file -Pattern "$($Line.number)" -Encoding default -Context 0, 1 | ForEach-Object {
= $_.Line
= $_.Context.PostContext
}
$ListOrg = [pscustomobject]@{
Line_org =
Line_GTU_org =
}
$LinesOriginal = $LinesOriginal + $ListOrg
$lineNew = $ListOrg.Line_org | foreach { $_ + "|$($line.A)|$($line.B)" }
$GTUNew = $ListOrg.Line_GTU_org | foreach { $_ + "|$($line.ValueofB)" }
$ListNew = [pscustomobject]@{
Line_new = $lineNew
Line_GTU_new = $GTUNew
Line_org = $ListOrg.Line_org
Line_GTU_org = $ListOrg.Line_GTU_org
}
$LinesToChange = $LinesToChange + $ListNew
}
输出的是一个对象$LinesToChange,它有原来的线条和改变后的线条。问题是我不知道如何使用它来更改 txt 文件。我尝试了几种方法并最终得到了包含更新行的文件,但所有其他方法都加倍了(我尝试了 foreach)或者 PS 正在使用整个 RAM 并且无法完成工作:)
我最近的想法是使用类似的东西:
(Get-Content -Path $file) | ForEach-Object {
$line = $_
$LinesToChange.GetEnumerator() | ForEach-Object {
if ($line -match "$($LinesToChange.Line_org)") {
$line = $line -replace "$($LinesToChange.Line_org)", "$($LinesToChange.Line_new)"
}
if ($line -match "$($LinesToChange.Line_GTU_org)") {
$line = $line -replace "$($LinesToChange.Line_GTU_org)", "$($LinesToChange.Line_GTU_new)"
}
}
} | Set-Content -Path Somehere\newfile.txt
起初看起来很有希望,但变量 $line 包含所有行,因此找不到匹配项。
我还需要确保第二行直接在第一行下方(这不太可能,但可能会有两行或更多行具有相同的数据,而“数字”来自CSV 文件是唯一的)因此最好在更改 txt 文件时需要找到两行的匹配项;简而言之:
找到这两行:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere|||||
2|zwol|9,00|9,00|0,00
将它们更改为:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere||||||0|1
2|zwol|9,00|9,00|0,00|AAA_01,AAA_03
对 $LinesToChange
中的所有行执行此操作
任何帮助将不胜感激!
您好!
你那里有一些奇怪的文本文件,但无论如何,应该这样做:
# read in the text file as string array
$txt = Get-Content -Path '<PathToTheTextFile>'
$csv = Import-Csv -Path '<PathToTheCSVFile>' -Delimiter ';'
# loop through the items (rows) in the CSV and find matching lines in the text array
foreach ($item in $csv) {
$match = $txt | Select-String -Pattern ('|{0}|' -f $item.Number) -SimpleMatch
if ($match) {
# update the matching text line (array indices count from 0, so we do -1)
$txt[$match.LineNumber -1] += ('|{0}|{1}' -f $item.A, $item.B)
# update the line following
$txt[$match.LineNumber] += ('|{0}' -f $item.ValueOfB)
}
}
# show updated text on screen
$txt
# save updated text to file
$txt | Set-Content -Path 'Somehere\newfile.txt'
我正在编写一个脚本,它将向 txt 文件添加一些附加信息。这些信息存储在 CSV 文件中,如下所示(每次启动脚本时数据都会不同):
Number;A;B;ValueOfB
FP01340/05/20;0;1;GTU_01,GTU_03
FP01342/05/20;1;0;GTU01
txt 文件如下所示(当然每次里面的数据都会不同):
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere|||||
2|zwol|9,00|9,00|0,00
2|23|157,91|194,23|36,32
1|1|FP01341/05/20|2020-05-02|2020-05-02|2020-05-02|12,19|14,99|2,80|Some info |2222222|blabla|11-111 something||||
2|23|12,19|14,99|2,80
1|1|FP01342/05/20|2020-05-02|2020-05-02|2020-05-02|525,36|589,64|64,28|bla|222222|blba 36||62030|something||
2|5|213,93|224,63|10,70
2|8|120,34|129,97|9,63
2|23|191,09|235,04|43,95
我需要做的是找到包含 'Number' 的行,然后从 CSV 中以以下形式添加值 'A' 和 'B':|0|1 然后在下面第一行的末尾,以 |AAA_01、AAA_03
的形式添加 'ValueofB'所以前两行最后应该是这样的:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere||||||0|1
2|zwol|9,00|9,00|0,00|AAA_01,AAA_03
2|23|157,91|194,23|36,32
其余的行不应该被触及。
我制作了一个脚本,它使用带有上下文的 select-string 方法来查找我需要的内容 - 将其放入一个对象中,然后将我需要的内容添加到之前找到的字符串中,并将其放入一个另一个对象。
我的脚本如下:
$csvFile = Import-Csv -Path Somepath\file.csv -Delimiter ";"
$file = "Somepath2\SomeName.txt"
$LinesToChange = @()
$script:LinesToChange = $LinesToChange
$LinesOriginal = @()
$script:LinesOriginal = $LinesOriginal
foreach ($line in $csvFile) {
Select-String -Path $file -Pattern "$($Line.number)" -Encoding default -Context 0, 1 | ForEach-Object {
= $_.Line
= $_.Context.PostContext
}
$ListOrg = [pscustomobject]@{
Line_org =
Line_GTU_org =
}
$LinesOriginal = $LinesOriginal + $ListOrg
$lineNew = $ListOrg.Line_org | foreach { $_ + "|$($line.A)|$($line.B)" }
$GTUNew = $ListOrg.Line_GTU_org | foreach { $_ + "|$($line.ValueofB)" }
$ListNew = [pscustomobject]@{
Line_new = $lineNew
Line_GTU_new = $GTUNew
Line_org = $ListOrg.Line_org
Line_GTU_org = $ListOrg.Line_GTU_org
}
$LinesToChange = $LinesToChange + $ListNew
}
输出的是一个对象$LinesToChange,它有原来的线条和改变后的线条。问题是我不知道如何使用它来更改 txt 文件。我尝试了几种方法并最终得到了包含更新行的文件,但所有其他方法都加倍了(我尝试了 foreach)或者 PS 正在使用整个 RAM 并且无法完成工作:)
我最近的想法是使用类似的东西:
(Get-Content -Path $file) | ForEach-Object {
$line = $_
$LinesToChange.GetEnumerator() | ForEach-Object {
if ($line -match "$($LinesToChange.Line_org)") {
$line = $line -replace "$($LinesToChange.Line_org)", "$($LinesToChange.Line_new)"
}
if ($line -match "$($LinesToChange.Line_GTU_org)") {
$line = $line -replace "$($LinesToChange.Line_GTU_org)", "$($LinesToChange.Line_GTU_new)"
}
}
} | Set-Content -Path Somehere\newfile.txt
起初看起来很有希望,但变量 $line 包含所有行,因此找不到匹配项。
我还需要确保第二行直接在第一行下方(这不太可能,但可能会有两行或更多行具有相同的数据,而“数字”来自CSV 文件是唯一的)因此最好在更改 txt 文件时需要找到两行的匹配项;简而言之:
找到这两行:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere|||||
2|zwol|9,00|9,00|0,00
将它们更改为:
1|1|FP01340/05/20|2020-05-02|2020-05-02|2020-05-02|166,91|203,23|36,32|nothing interesting 18|33333|63-111 somewhere||||||0|1
2|zwol|9,00|9,00|0,00|AAA_01,AAA_03
对 $LinesToChange
中的所有行执行此操作任何帮助将不胜感激!
您好!
你那里有一些奇怪的文本文件,但无论如何,应该这样做:
# read in the text file as string array
$txt = Get-Content -Path '<PathToTheTextFile>'
$csv = Import-Csv -Path '<PathToTheCSVFile>' -Delimiter ';'
# loop through the items (rows) in the CSV and find matching lines in the text array
foreach ($item in $csv) {
$match = $txt | Select-String -Pattern ('|{0}|' -f $item.Number) -SimpleMatch
if ($match) {
# update the matching text line (array indices count from 0, so we do -1)
$txt[$match.LineNumber -1] += ('|{0}|{1}' -f $item.A, $item.B)
# update the line following
$txt[$match.LineNumber] += ('|{0}' -f $item.ValueOfB)
}
}
# show updated text on screen
$txt
# save updated text to file
$txt | Set-Content -Path 'Somehere\newfile.txt'