【问题标题】:Powershell: Read Text file line by line and split on "|"Powershell:逐行读取文本文件并在“|”上拆分
【发布时间】:2019-05-14 20:19:44
【问题描述】:

我无法使用“|”将一行拆分为一个数组在文本文件中并按一定顺序重新组装它。与文本文件中的原始行一样,有多行。

这是原行:

80055555|Lastname|Firstname|AidYear|DCDOCS|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf

我需要它看起来像这样:

80055555|DCDOCS|Lastname|Firstname|AidYear|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf

这是我正在使用的代码:

$File = 'c:\Names\Complete\complete.txt'
$Arr = $File -split '|'
foreach ($line in Get-Content $File)
{
  $outputline = $Arr[0] + "|" + $Arr[4] + "|" + $Arr[1] + "|" + $Arr[2] + "|" + 
    "@@" + $Arr[5] |
      Out-File -filepath "C:\Names\Complete\index.txt" -Encoding "ascii" -append 
}

【问题讨论】:

    标签: powershell csv text-parsing


    【解决方案1】:

    您需要自己处理文件的每一行,然后拆分它们。

    $File = get-content "D:\test\1234.txt"
    foreach ($line in $File){
        $Arr = $line.Split('|')
        [array]$OutputFile +=  $Arr[0] + "|" + $Arr[4] + "|" + $Arr[1] + "|" + $Arr[2] + "|" + "@@" + $Arr[5] 
    }
    $OutputFile | out-file -filepath "D:\test\4321.txt" -Encoding "ascii" -append 
    

    编辑:感谢 LotPings 基于-join 和避免使用+= 来构建数组的替代建议(这是低效的,因为它在每次迭代时都重建数组):

    $File = get-content "D:\test\1234.txt"
    $OutputFile = foreach($line in $File){($line.split('|'))[0,4,1,2,3,5] -Join '|'}
    $OutputFile | out-file -filepath "D:\test\4321.txt" -Encoding "ascii"
    

    【讨论】:

      【解决方案2】:

      由于您的输入文件实际上是一个没有标题的 CSV 文件,并且字段由管道符号 | 分隔,为什么不使用 Import-Csv 像这样:

      $fileIn  = 'C:\Names\Complete\complete.txt'
      $fileOut = 'C:\Names\Complete\index.txt'
      (Import-Csv -Path $File -Delimiter '|' -Header 'Item','LastName','FirstName','AidYear','Type','FileName' | 
          ForEach-Object {
              "{0}|{1}|{2}|{3}|{4}|{5}" -f $_.Item, $_.Type, $_.LastName, $_.FirstName, $_.AidYear, $_.FileName
          }
      ) | Add-Content -Path $fileOut -Encoding Ascii
      

      【讨论】:

      • 超级!它工作得很好!我也会将此添加到我的工具包中以供将来使用!
      【解决方案3】:

      提供更符合 PowerShell 习惯的解决方案:

      # Sample input line.
      $line = '80055555|Lastname|Firstname|AidYear|DCDOCS|D:\BDMS_UPLOAD\800123456_11-13-2018 14-35-53 PM_1.pdf'
      
      # Split by '|', rearrange, then re-join with '|'
      ($line -split '\|')[0,4,1,2,3,5] -join '|'
      

      请注意 PowerShell 的索引语法(在 [...] 内部)如何足够灵活,可以接受要提取的任意索引数组(列表)。

      还要注意-split 的RHS 操作数是\|,即转义 | 字符,因为| 在那里有特殊含义(因为它被解释为正则表达式)。

      把它们放在一起:

      $File = 'c:\Names\Complete\complete.txt'
      Get-Content $File | ForEach-Object {
        ($_ -split '\|')[0,4,1,2,3,5] -join '|'
      } | Out-File -LiteralPath C:\Names\Complete\index.txt -Encoding ascii
      

      至于你尝试了什么

      $Arr = $File -split '|'

      主要问题是-split 操作应用于输入文件路径,而不是文件的内容

      其次,如上所述,要由 literal | 字符分割,\| 必须传递给 -split,因为它需要一个 regex (正则表达式)。

      另外,与-Append 一起使用在循环中Out-File 相比,使用ForEach-Object单个管道 更有效,如上所示.

      【讨论】: