问题
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:
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:
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!
回答1:
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 }
回答2:
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
}
来源:https://stackoverflow.com/questions/53054634/script-to-identify-specific-text-and-replace-with-text-from-another-column-witho