【问题标题】:How to read the first element of all Rows in a text file and then iterate over it in Powershell scripting?如何读取文本文件中所有行的第一个元素,然后在 Powershell 脚本中对其进行迭代?
【发布时间】:2018-10-10 06:24:32
【问题描述】:

我是 Powershell 脚本和编程方面的新手。我需要执行以下操作:

  • 有一个包含行数的文本文件,每一行都有用逗号分隔的元素。现在,有些行总是以“BB”开头,可能有数百个“BB”行。当它是“BB”时,我需要做一些改变等等。

我想遍历所有行,如果它以“BB”开头,那么我会做一些事情。下面只是一个测试代码,因为我不知道在这里做什么。我怎样才能以最有效的方式做到这一点,以便它快速且性能较低 开销。

更新:现在,问题是“BB”行的第一个实例(奇怪)的日期没有更新。这是我写的更新代码:

现在,我应该在“Foreach”循环之后写出文件,因为它会一次又一次地写入文件。此外,何时使用管道字符 (|)。

$path = 'C:\CE\InputFile\file_test1.txt'
$Filedata = Get-Content $path

$CurrentDate = (Get-Date).ToString("yymmdd")

foreach($Row in $Filedata){
if($Row.split(",")[0] -eq "BB")
{
    $Row2Date = $Row.Split(",")[4] 
    $Temp = $Filedata -replace $Row2Date, $CurrentDate | 

Out-File C:\outdata\outputfile1.txt

}

}

AA, field1, field2, field3, field4, field5.....
BB, field1, field2, field3, field4, field5.....
CC, field1, field2, field3, field4, field5.....
DD, field1, field2, field3, field4, field5.....
BB, field1, field2, field3, field4, field5.....

【问题讨论】:

  • 如果文件是逗号分隔的,为什么不使用 Import-Csv 在必要时插入虚拟标题?
  • 嗨@LotPings,这就是问题所在。我无法在文本文件中插入虚拟标题。
  • 月份格式说明符必须为大写(Get-Date).ToString("yyMMdd")

标签: arrays powershell collections iteration powershell-3.0


【解决方案1】:

随着要求的变化,我发布了一个新答案。
由于您想更改第 5 个字段,因此我扩展了示例文件

## Q:\Test\2018\04\30\SO_50095738_2.ps1
$FilePath1 = 'C:\CE\InputFile\file_test1.txt'
$FilePath2 = 'C:\outdata\outputfile1.txt'

$FileData1 = Get-Content $FilePath1
$CurrentDate = (Get-Date).ToString("yyMMdd")

$FileData2 = ForEach($Row in $Filedata1){
    If ($Row.split(",")[0] -eq "BB"){
       $Row  -replace ($Row.Split(",")[4]), $CurrentDate
    } else {
       $Row
    }
} 
Out-File -FilePath $FilePath2 -InputObject $FileData2

样本输出

AA, field1, field2, field3, field4, field5.....
BB, field1, field2, field3,180402, field5.....
CC, field1, field2, field3, field4, field5.....
DD, field1, field2, field3, field4, field5.....
BB, field1, field2, field3,180402, field5.....

【讨论】:

  • 感谢您的正确回答。它就像一个魅力!现在,所有“BB”记录都有更新日期。
【解决方案2】:
  • 文件中不需要插入Headers,Import-Csv可以处理 这个。
  • 您可以删除标题,请参阅注释掉的变体。
  • Export-Csv 双引号所有字段可能是一个问题。
  • 必要时也可以处理。

## Q:\Test\2018\04\30\SO_50095738.ps1
$FilePath = '.\TestFile001.txt' 
$FileData = Import-Csv $FilePath -Header H0,H1,H2,H3
$test1 = 'test1'

ForEach($row in $FileData ) {
  If ($row.H0 -eq 'BB' ) {
    $row.H2 = $test1
  }
}
$FileData | Export-csv $FilePath -NoTypeInformation

## Variant with NoHeader
# $FileData|ConvertTo-Csv -NoTypeInfo|Select -Skip 1|Set-Content $FilePath

## Variant with no header and no quotes
# ($FileData|ConvertTo-Csv -NoTypeInfo).Replace('","',', ').Trim('"')|Select -Skip 1|Set-Content $FilePath

Get-Content $FilePath

样本输出:

"H0","H1","H2","H3"
"AA","field1","field 2","field 3....."
"BB","field1","test1","field 3....."
"CC","field1","field 2","field 3....."
"DD","field1","field 2","field 3....."
"BB","field1","test1","field 3....." 

【讨论】:

  • 现在,另一个问题是,循环一次又一次地运行,我想将更新的输出文件保存在一个目录中。是否可以一次性更新 ex("500 "BB" 记录,然后保存文件输出文件,一次在目录中) Out-File C:\PS\outfile1.txt
  • 对不起,我无法跟上。脚本是否按您的要求工作?如果是,请考虑接受和/或投票。否则,如果您想保存到另一个文件/路径,请为此创建一个 var 并使用它们。照原样 - 脚本将更改内存中满足 $FileData 变量中条件的 所有 行,直到您保存回任何位置。
  • 不,一行中有很多项目,并且在其他文件中发生了变化,所以我不能使用标题。
【解决方案3】:

使用 split 获取第一个“列”

$FileContent =Get-Content -Path "SomePath\test.txt"
foreach ($Row in $FileContent) {
    if ($Row.Split(",")[0] -eq "BB") {
        $NewRow = $Row -replace "BB", "XX"
        $FileContent = $FileContent.Replace($Row,$NewRow)
    }
}

【讨论】:

  • 感谢您的帮助!但是,只有第一个“BB”记录更新,而其他“实例”没有改变。
  • 我没有解决我的问题。也许变量“$Row”在文件中不包含 thr 记录。此外,我们如何根据换行符/eol 在数组中插入行。 if ($Filedata.Split(",")[0] -eq "BB") ,这找不到我的“BB”记录。
  • 您不能使用包含全部数据的变量。遍历行并拆分行,看看我的例子
  • 现在,另一个问题是,循环一次又一次地运行,我想将更新的输出文件保存在一个目录中。是否可以一次性更新 ex("500 "BB" 记录,然后保存文件输出文件,一次在目录中) Out-File C:\PS\outfile1.txt
猜你喜欢
  • 2018-01-15
  • 2016-02-06
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
  • 2018-07-03
相关资源
最近更新 更多