Parsing 通过Powershell解析和更改系统的输出

Parsing 通过Powershell解析和更改系统的输出,parsing,powershell,awk,Parsing,Powershell,Awk,最初我必须声明,到目前为止,我对powershell几乎没有经验。以前的系统为我生成了错误的输出。所以我想用PowerShell来改变这一点。从系统中,我得到如下输出: TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^...^|^Y^|^NOT IN^|^('8','9','10','11','12') TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^

最初我必须声明,到目前为止,我对powershell几乎没有经验。以前的系统为我生成了错误的输出。所以我想用PowerShell来改变这一点。从系统中,我得到如下输出:

TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^...^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^...^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
$sp = '^|^'

Get-Content 'C:\path\to\input.txt' | % {
  $a = $_ -split [regex]::Escape($sp)
  for ($i=2; $i -lt $a.length; $i+=3) {
    "{0}$sp{1}$sp{2}$sp{3}$sp{4}" -f $a[0,1,$i,($i+1),($i+2)]
  }
} | Set-Content 'C:\path\to\output.txt'
当您查看它时,每一行都有一个起始部分(TEST1^^^^9999^^^^^^^^),后跟a1到a-n元组(例如:Y^^^^^^不在^^^^^^('1','2','3')^^^^^)

我希望它看起来是这样的:

TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')
TEST1^|^9999^|^N^|^LIKE^|^('4','5','6','7')
TEST1^|^9999^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')
TEST2^|^9998^|^N^|^LIKE^|^('6','7','8','9')
TEST2^|^9998^|^Y^|^NOT IN^|^('1','2','15','16','17')
TEST2^|^9998^|^Y^|^NOT IN^|^('18','19','20','21','22')
因此,元组应每行打印一次,起始部分附在前面

我的解决方法是,但是到目前为止,我还不了解如何处理不确定数量的元组,以及如何重复起始块


我提前非常感谢你的帮助

将任意长度的字符串记录解析为行记录非常容易出错。一个简单的解决方案是逐行处理数据并创建输出

下面是如何处理单行的简单示例。处理整个输入文件和编写输出对于读者来说是一个微不足道的练习

$s = "TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')"
$t = $s.split('\)', [StringSplitOptions]::RemoveEmptyEntries)
$testNum = ([regex]::match($t[0], "(?i)(test\d+\^\|\^\d+)")).value # Hunt for 1st colum values
$t[0] = $t[0] + ')' # Fix split char remove
for($i=1;$i -lt $t.Length; ++$i) { $t[$i] = $testNum + $t[$i] + ')' } # Add 1st colum and split char remove

$t
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')
TEST1^|^9999^|^N^|^LIKE^|^('4','5','6','7')
TEST1^|^9999^|^Y^|^NOT IN^|^('8','9','10','11','12')

将任意长度的字符串记录解析为行记录非常容易出错。一个简单的解决方案是逐行处理数据并创建输出

下面是如何处理单行的简单示例。处理整个输入文件和编写输出对于读者来说是一个微不足道的练习

$s = "TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')"
$t = $s.split('\)', [StringSplitOptions]::RemoveEmptyEntries)
$testNum = ([regex]::match($t[0], "(?i)(test\d+\^\|\^\d+)")).value # Hunt for 1st colum values
$t[0] = $t[0] + ')' # Fix split char remove
for($i=1;$i -lt $t.Length; ++$i) { $t[$i] = $testNum + $t[$i] + ')' } # Add 1st colum and split char remove

$t
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')
TEST1^|^9999^|^N^|^LIKE^|^('4','5','6','7')
TEST1^|^9999^|^Y^|^NOT IN^|^('8','9','10','11','12')

数据看起来非常规则,因此您可以使用
|
作为分隔符循环数据,并在3秒内计算以下单元格:

$data = @"
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
"@

$data.split("`n") | % { 
    $ds = $_.split("|")
    $heading = "$($ds[0])|$($ds[1])"
    $j = 0

    for($i = 2; $i -lt $ds.length; $i += 1) {
        $line += "|$($ds[$i])" -replace "\^(\((?:'\d+',?)+\))\^?",'$1'
        $j += 1
        if($j -eq 3) { 
            write-host $heading$line
            $line = ""
            $j = 0
        }
    }
}

数据看起来非常规则,因此您可以使用
|
作为分隔符循环数据,并在3秒内计算以下单元格:

$data = @"
TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
"@

$data.split("`n") | % { 
    $ds = $_.split("|")
    $heading = "$($ds[0])|$($ds[1])"
    $j = 0

    for($i = 2; $i -lt $ds.length; $i += 1) {
        $line += "|$($ds[$i])" -replace "\^(\((?:'\d+',?)+\))\^?",'$1'
        $j += 1
        if($j -eq 3) { 
            write-host $heading$line
            $line = ""
            $j = 0
        }
    }
}

我将在
^ | ^
处拆分行,并在循环中重新组合结果数组的字段。大概是这样的:

TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^...^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^...^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
$sp = '^|^'

Get-Content 'C:\path\to\input.txt' | % {
  $a = $_ -split [regex]::Escape($sp)
  for ($i=2; $i -lt $a.length; $i+=3) {
    "{0}$sp{1}$sp{2}$sp{3}$sp{4}" -f $a[0,1,$i,($i+1),($i+2)]
  }
} | Set-Content 'C:\path\to\output.txt'

我将在
^ | ^
处拆分行,并在循环中重新组合结果数组的字段。大概是这样的:

TEST1^|^9999^|^Y^|^NOT IN^|^('1','2','3')^|^N^|^LIKE^|^('4','5','6','7')^|^...^|^Y^|^NOT IN^|^('8','9','10','11','12')
TEST2^|^9998^|^Y^|^NOT IN^|^('4','5','6')^|^N^|^LIKE^|^('6','7','8','9')^|^...^|^Y^|^NOT IN^|^('1','2','15','16','17')^|^Y^|^NOT IN^|^('18','19','20','21','22')
$sp = '^|^'

Get-Content 'C:\path\to\input.txt' | % {
  $a = $_ -split [regex]::Escape($sp)
  for ($i=2; $i -lt $a.length; $i+=3) {
    "{0}$sp{1}$sp{2}$sp{3}$sp{4}" -f $a[0,1,$i,($i+1),($i+2)]
  }
} | Set-Content 'C:\path\to\output.txt'

哇,谢谢你的努力,我会试试这个,然后回来找你。对于初学者,如何在txt文件中用自动抓取第一行来替换第1行?哇,谢谢你的努力,我会尝试一下,然后再回来找你。对于初学者来说,如何用自动抓取txt文件中的第一行来替换第1行?因此我需要在以后删除每个元组中的“^”?有简单的功能吗?抱歉问了这么多基本的问题,你们帮了我大忙。编辑:没关系,我说我的输出中也有它们,请看编辑。现在,当添加到
$line
时,我们可以使用正则表达式查看单元格是否为元组,并替换掉
^
字符(如果数据总是以
^
结尾)?我对
-replace
行做了一个小小的更新,如果是这样的话,我会对它进行解释。每行的最后一个元组没有像^ | ^这样的分隔符。帮了大忙,谢谢。你救了我一夜的试错。现在,我将尝试理解它,以用于进一步的工作。多亏了其他贡献者,tooSo我以后需要删除每个元组中的“^”?有简单的功能吗?抱歉问了这么多基本的问题,你们帮了我大忙。编辑:没关系,我说我的输出中也有它们,请看编辑。现在,当添加到
$line
时,我们可以使用正则表达式查看单元格是否为元组,并替换掉
^
字符(如果数据总是以
^
结尾)?我对
-replace
行做了一个小小的更新,如果是这样的话,我会对它进行解释。每行的最后一个元组没有像^ | ^这样的分隔符。帮了大忙,谢谢。你救了我一夜的试错。现在,我将尝试理解它,以用于进一步的工作。也要感谢其他的贡献者