Script to identify specific text and replace with

2019-08-27 04:17发布

I have a .txt file that contains various lines of data which is organised by text starting at specific column numbers - basically a table of data.

The below example shows where each column starts: example

I would like the script to find all lines which contain "-" in column 555 and replace this with the first 19 characters found in column 450 without effecting any line spacing.

Desired output for this example: enter image description here

As you can see "Brooklyn" has been copied from column 450 and replaced the "-" in column 555.

Please note:

  • The script will need to run through multiple .txt files located in the same folder
  • The .txt files contain various number of lines e.g some files might have 20 lines whereas others may have 100

Also, In regards to checking each .txt in a given folder - I will be using the below. Please let me know if it possible with this.

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

Could someone please help with scripting this in PowerShell.

Thank you in advance!

2条回答
三岁会撩人
2楼-- · 2019-08-27 04:44

this is really rather ugly, but it seems to do the job. [grin]

<#
_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)
        }
    }

output ...

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

what it does ...

  • finds the trigger text
  • copies the source text
  • removes the current destination text
  • inserts the replacement for the above

as requested, here's a full script that handles reading the files & writing out the changes. it does NOT overwrite the source files, but the comments tell one how to make that change.

# 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
    }
查看更多
叼着烟拽天下
3楼-- · 2019-08-27 05:04
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 }
查看更多
登录 后发表回答