识别特定文本并用另一列中的文本替换而不影响列位置的脚本

时间:2018-10-29 22:11:55

标签: powershell text fixed-width

我有一个.txt文件,其中包含各种数据行,这些数据行是根据特定的列号(基本上是一个数据表)从文本开始组织的。

下面的示例显示每列的起始位置: example

我希望脚本在列555中查找包含“-”的所有行,并用在列450中找到的前19个字符替换它,而不会影响任何行距。

此示例的所需输出: enter image description here

如您所见,“布鲁克林”已从第450列复制并替换为第555列中的“-”。

  

请注意:

     
      
  • 该脚本将需要遍历位于同一文件夹中的多个.txt文件
  •   
  • .txt文件包含许多行,例如,某些文件可能有20行,而其他文件可能有100行
  •   

此外,关于检查给定文件夹中的每个.txt-我将使用以下内容。请让我知道是否可以这样做。

Get-ChildItem C:\Users\Desktop -Filter *.txt | 
ForEach-Object { 
Set-Content $_.FullName) }

请有人帮忙在PowerShell中编写脚本。

提前谢谢!

2 个答案:

答案 0 :(得分:0)

这确实很丑陋,但这似乎可以解决问题。 [咧嘴]

<#
_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
#>

$InStuff = @'
Alfa      Bravo     -         Delta     Echo      -         -         Foxtrot   Golf
Hotel     Inkblot   Joker     -         Kilo      -         Lima      Mike      Nova
'@ -split [environment]::NewLine

$ColSize = 10
$ColToCheck = 30
$TriggerText = '-'
$SourceCol = 10
$DestCol = 60
$SourceStopIndex = $SourceCol + $ColSize - 1

foreach ($IS_Item in $InStuff)
    {
    if ($IS_Item[$ColToCheck] -eq $TriggerText)
        {
        $SourceText = -join $IS_Item[$SourceCol..$SourceStopIndex]

        $IS_Item
        $IS_Item.Remove($DestCol, $ColSize).Insert($DestCol, $SourceText)
        }
    }

输出...

Hotel     Inkblot   Joker     -         Kilo      -         Lima      Mike      Nova
Hotel     Inkblot   Joker     -         Kilo      -         Inkblot   Mike      Nova

它做什么...

  • 找到触发文本
  • 复制源文本
  • 删除当前目标文本
  • 插入上述内容的替代物

根据要求,这是一个完整的脚本,用于处理读取文件和写出更改。它不会覆盖源文件,但是注释告诉您如何进行更改。

# create some testing files
$FileOneText = @'
Alfa      Bravo     -         Delta     Echo      -         -         Foxtrot   Golf
Hotel     Inkblot   Joker     -         Kilo      -         Lima      Mike      Nova
'@ | Set-Content "$env:TEMP\Jasdeep_01.txt"
$FileTwoText = @'
Alfa      Bravo     -         -         Delta     -         Echo      Foxtrot   Golf
Hotel     Inkblot   Joker     -         Kilo      -         Lima      Mike      Nova
'@ | Set-Content "$env:TEMP\Jasdeep_02.txt"
$FileThreeText = @'
Alfa      Bravo     -         Delta     Echo      Foxtrot   Golf      Hotel     Inkblot
Joker     Kilo      Lima      -         Mike      Nova      Oscar     Papa      Quebec
'@ | Set-Content "$env:TEMP\Jasdeep_03.txt"

$ColSize = 10
$ColToCheck = 30
$TriggerText = '-'
$SourceCol = 10
$DestCol = 60

$SourceDir = $env:TEMP
$Filter = 'Jasdeep*.txt'

$FileList = Get-ChildItem -LiteralPath $SourceDir -Filter $Filter -File

foreach ($FL_Item in $FileList)
    {
    $ChangedContent = foreach ($Line in (Get-Content -LiteralPath $FL_Item.FullName))
        {
        if ($Line[$ColToCheck] -eq $TriggerText)
            {
            $SourceText = $Line.Substring($SourceCol, $ColSize)

            $Line.Remove($DestCol, $ColSize).Insert($DestCol, $SourceText)
            }
            else
            {
            $Line
            }
        }
    # for testing, i used new files for saving the changes
    $NewFileName = $FL_Item.FullName -replace $FL_Item.BaseName, ('{0}_{1}' -f $FL_Item.BaseName, 'Changed')
    #    comment out the line above &
    #    UN-comment the next line if you want to replace the originals
    #$NewFileName = $FL_Item.FullName
    $ChangedContent |
        Set-Content -LiteralPath $NewFileName
    }

答案 1 :(得分:0)

Get-ChildItem C:\input -Filter *.txt | 
    ForEach-Object {
        (Get-Content $_.FullName | ForEach-Object {
            if ($_[549] -eq '-') {                           # Array is 0-indexed
                -join ($_[0..548+449..467+568..$_.length])
            } else {$_}
        }) | Set-Content $_.FullName }