基于 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'