如何遍历文本文件的每个记录以替换字符串

时间:2019-12-10 22:55:32

标签: powershell

我有一个很大的.txt文件,其中包含记录,其中每条记录中的日期字符串需要增加2天,这将更新其右侧包含破折号的字段---------那个日期。例如,一条记录包含以下记录数据:

1440149049845_20191121000000 2019年11月22日-------- 0.000 0.013

我要用11/24/2019代替--------破折号(在日期11/22/2019加上2天),以便显示为:

1440149049845_20191121000000 11/22/2019 11/24/2019 0.000 0.013

我在单个记录上执行了替换操作,但是需要遍历整个.txt文件以更新所有记录。这是我尝试过的:

$inputRecords = get-content '\\10.12.7.13\vipsvr\Rancho\MRDF_Report\_Report.txt'

foreach ($line in $inputRecords)  
 {
    $item -match '\d{2}/\d{2}/\d{4}' 
    $inputRecords -replace '-{2,}',([datetime]$matches.0).adddays(2).tostring('MM/dd/yyyy') -replace '\b0\.000\b','0.412'
 }

我收到一个PS错误,指出:“无法将null转换为类型“ System.DateTime”

3 个答案:

答案 0 :(得分:0)

您大多有正确的想法,但是这里有一些建议的更改,但不完全按此顺序进行:

  1. 使用新文件,而不是尝试替换旧文件。

  2. 一次遍历一行,替换------,写入新文件。

  3. 使用'-match'而不是'-replace',因为正如您将在下面看到的那样,您需要比简单的'-replace'允许更多的操作捕获。

  4. 使用[datetime] :: parseexact而不是尝试强制转换捕获的文本。

[string[]]$inputRecords = get-content ".\linesource.txt"
[string]$outputRecords

foreach ($line in $inputRecords) {
    [string]$newLine = ""
    [regex]$logPattern = "^([\d_]+) ([\d/]+) (-+) (.*)$"
    if ($line -match $logPattern) {
        $origDate = [datetime]::parseexact($Matches[2], 'mm/dd/yyyy', $null)
        $replacementDate = $origDate.adddays(2)

        $newLine  = $Matches[1]
        $newLine += " " + $origDate.toString('mm/dd/yyyy')
        $newLine += " " + $replacementDate.toString('mm/dd/yyyy')
        $newLine += " " + $Matches[4]
    } else {
        $newLine = $line
    }
    $outputRecords += "$newLine`n"
}

$outputRecords.ToString()

即使您不使用整个解决方案,也希望至少有部分解决方案会对您有所帮助。

答案 1 :(得分:0)

对不起,为什么我们要使用RegEx做这么简单的事情?

如果文件中有不同格式的行,我可以看到它,您想确保您没有在操纵意外的行,但这未在问题中指出。即使如此,似乎您也不需要匹配该行中的任何内容。似乎在空格之间定界,这会使简单的拆分容易得多。

示例:

$File = "C:\temp\Test.txt"
$Output =
ForEach( $Line in Get-Content $File)
{
$TmpArray = $Line.Split(' ')
$TmpArray[2] = (Get-Date $TmpArray[1]).AddDays(2).ToString('M/dd/yyyy')
$TmpArray -join ' '
} 

数组中的第三个元素进行计算并重新分配值...

请注意,没有使用+ =运算符,与仅将输出分配给变量相比,这非常慢。我不会做任何事情,但考虑到我们不知道文件有多大...此外,在“ mm / dd / yyyy”之前给出的字符串格式将导致本月的00,例如“ 00” / 22/2019”,因此我将其更改为“ M / dd / yyyy”

如果需要,您仍然可以添加逻辑以跳过不必要的行...

您可以将$ Output发送到类似$Output | Out-File <FilePath>的文件中

或者可以将其转换为单个管道,使用| ForEach{...}而不是ForEach(.. in ..)直接输出到文件如果文件确实很大并且在内存中保留$ Output是一个很好的问题替代。

让我知道是否有帮助。

答案 2 :(得分:0)

使用来自adamt8和Steven的建议代码,我添加了2条echo语句以显示变量$ logpattern和$ line中显示的内容,因为它无法识别要更新的字符模式。这是回显中显示的内容:

选项MatchTimeout RightToLeft

CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
   无-00:00:00.0010000错误 CalNOD01 1440151020314_20191205000000 2019年6月12日--------
   无-00:00:00.0010000错误

这是渲染的输出:

CalNOD01 1440151020208_20191205000000 12/06/2019 12/10/2019
CalNOD01 1440151020314_20191205000000 12/06/2019 --------

这是使用的代码:

enter image description here