【问题标题】:Powershell - reading ahead and WhilePowershell - 提前阅读
【发布时间】:2015-08-17 20:44:38
【问题描述】:

我有一个格式如下的文本文件:

.....
ENTRY,PartNumber1,,, 
FIELD,IntCode,123456
...
FIELD,MFRPartNumber,ABC123,,,
...
FIELD,XPARTNUMBER,ABC123
...
FIELD,InternalPartNumber,3214567
...
ENTRY,PartNumber2,,,
...
...

... 表示这些字段之间还有其他数据。 唯一我可以确定的是,以ENTRY 开头的字段是一组新记录。以FIELD 开头的行可以是任意顺序,并不是所有的行都可能出现在每组数据中。

  1. 我需要读入一大块数据
  2. 搜索与 字符串 ABC123
  3. 如果找到 ABC123,则搜索是否存在 InternalPartNumber 字段并返回该行数据。

我还没有看到一种使用Get-Content 的方法,它可以将可变数量的行作为一组读取并能够搜索它。

这是我目前拥有的代码,它将读取一个文件,搜索一个字符串并用另一个替换它。我希望可以修改它以在这种情况下使用。

$ftype = "*.txt"
$fnames = gci -Path $filefolder1 -Filter $ftype -Recurse|% {$_.FullName}
$mfgPartlist = Import-Csv -Path "C:\test\mfrPartList.csv"

foreach ($file in $fnames) {
   $contents = Get-Content -Path $file
   foreach ($partnbr in $mfgPartlist) {
        $oldString = $mfgPartlist.OldValue
        $newString = $mfgPartlist.NewValue
        if (Select-String -Path $file -SimpleMatch $oldString -Debug -Quiet) {
           $stringData = $contents -imatch $oldString
           $stringData = $stringData -replace "[\n\r]","|"
           foreach ($dataline in $stringData) {
                $file +"|"+$stringData+"|"+$oldString+"|"+$newString|Out-File "C:\test\Datachanges.txt" -Width 2000 -Append
               }
           $contents = $contents -replace $oldString $newString
           Set-Content -Path $file -Value $contents
         }
   }
}

有没有办法使用 Powershell 读取和搜索“块”中的文本文件?还是进行预读并确定要搜索的内容?

【问题讨论】:

  • 这个文件有多大?
  • 你用的是什么版本的powershell? Get-Host
  • 使用 Powershell 3.0。此外 - 文件大小从 2-3k 到大约 150k 不等。 Ballpark 估计是 100k 文件大小 = 2000 行文本。多个文件夹和子文件夹中有数百个文件。

标签: powershell csv search text


【解决方案1】:

假设你的罚款不是太大而不能一次全部读入内存:

$Text = Get-Content testfile.txt -Raw

($Text -split '(?ms)^(?=ENTRY)') |
 foreach { 
  if ($_ -match '(?ms)^FIELD\S+ABC123')
   {$_ -replace '(?ms).+(^Field\S+InternalPartNumber.+?$).+','$1'}
}

FIELD,InternalPartNumber,3214567

这会将整个文件作为单个多行字符串读取,然后在以 'ENTRY' 开头的任何行的开头拆分它。然后,它会针对包含“ABC123”的 FIELD 行测试每个段,如果是,则删除除 InternalPartNumber 的 FIELD 行之外的所有内容。

【讨论】:

    【解决方案2】:

    这不是我最好的作品,因为我刚从假期回来。您可以使用 while 循环读取文本并设置条目标志以大块地吞噬文本。但是,如果您的文件不是太大,那么您可以一次读取文本文件并使用正则表达式拆分块,然后进行相应处理。

    $pattern = "ABC123"
    $matchedRowToReturn = "InternalPartNumber"
    $fileData = Get-Content "d:\temp\test.txt" | Where-Object{$_ -match '^(entry|field)'} | Out-String
    $parts = $fileData | Select-String '(?smi)(^Entry).*?(?=^Entry|\Z)' -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value
    $parts | Where-Object{$_ -match $pattern} | Select-String "$matchedRowToReturn.*$" | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value
    

    这将在文本文件中读取,将所有与条目或字段无关的行删除为一个长字符串,并将其拆分为以“条目”开头的行开头的块。

    然后我们删除那些不包含$pattern 的“部分”。在其余匹配项中提取InternalPartNumber 行并呈现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多