问题
My file consists of following data (no header)
DEPOSIT ADD 123456789 (VALUE)(VARIABLE) NNNN VALUEVARIABLE
DEPOSIT ADD 234567890 (VALUE)(P75) NNNN VALUEVARIABLE
DEPOSIT ADD 345678901 (VALUE)(VARIABLE) NNNN VALUEVARIABLE
This is a tab delimited text file. There are total of 5 columns. (123456789 (VALUE)(VARIABLE) is a single value column)
My requirements are:
- I need to fetch only the row which contains P75 to update in the same file.
- I have to replace the values in Col3,Col4 and in Col5 after fetching P75 other rows should be unaffected.
from
DEPOSIT ADD 234567890 (VALUE)(P75) NNNN VALUEVARIABLE
to
DEPOSIT ADD 234567890 (VTG)(SPVTG) TCM VTGSPVTG
- Only the records which contains P75 should be updated like this. The replace values are same for all selected records.
My script which I have written is
$original_file='C:\Path\20200721130155_copy.txt' -header Col1,Col2,Col3,Col4,Col5,| Select Col3,Col4,Col5
(Get-Content $original_file) |ForEach-Object {
if($_.Col3 -match '(VALUE)(P75)')
{
$_ -replace '(VALUE)(P75)', '(VTG)(SPVTG)' `
-replace 'VALUEVARIABLE', 'VTGSPVTG' `
-replace 'NNNN', 'TCM' `
}
$_
}| Set-Content $original_file+'_new.txt' -Force
I am getting output file with same content. The file is not getting updated.
Please advice.
Thanks
回答1:
You can do the following:
$newfile = "{0}_new.txt" -f $original_file
Get-Content $original_file | Foreach-Object {
if ($_ -match '\(VALUE\)\(P75\)') {
$_ -replace '\(VALUE\)\(P75\)','(VTG)(SPVTG)' -replace 'VALUEVARIABLE', 'VTGSPVTG' -replace 'NNNN', 'TCM'
} else {
$_
}
} | Set-Content $newfile -Force
Since -replace
uses regex, you must backslash escape special regex characters like (
and )
.
Since $_
is the current line read from Get-Content
without -Raw
, you will need to output $_
if you want to make no changes. If you do want to replace text, then $_ -replace 'regex','text'
will output that line with the replaced text.
Alternatively, you can apply the same logic above in a switch
statement, which is more efficient:
$newfile = "{0}_new.txt" -f $original_file
$(switch -regex -file $original_file {
'\(VALUE\)\(P75\)' {
$_ -replace '\(VALUE\)\(P75\)','(VTG)(SPVTG)' -replace 'VALUEVARIABLE', 'VTGSPVTG' -replace 'NNNN', 'TCM'
}
default { $_ }
}) | Set-Content $newfile -Force
回答2:
You can use Import-Csv -Delimiter "`t"
to import the data of the original file.
Then loop over the items and change the values if Col3 matches the search text.
$original_file = 'C:\Path\20200721130155_copy.txt'
$out_file = $original_file -replace '\.txt$', '_new.txt'
(Import-Csv -Path $original_file -Delimiter "`t" -Header 'Col1','Col2','Col3','Col4','Col5') | ForEach-Object {
if( $_.Col3 -like '*(*)*(P75)') {
$_.Col3 = $_.Col3 -replace '\([^)]+\)\(P75\)$', '(VTG)(SPVTG)'
$_.Col4 = 'TCM'
$_.Col5 = 'VTGSPVTG'
}
# rejoin the fields and output the line
$_.PsObject.Properties.Value -join "`t"
} | Set-Content -Path $out_file -Force
Output will be
DEPOSIT ADD 123456789 (VALUE)(VARIABLE) NNNN VALUEVARIABLE DEPOSIT ADD 234567890 (VTG)(SPVTG) TCM VTGSPVTG DEPOSIT ADD 345678901 (VALUE)(VARIABLE) NNNN VALUEVARIABLE
Regex details for -replace
:
\( Match the character “(” literally [^)] Match any character that is NOT a “)” + Between one and unlimited times, as many times as possible, giving back as needed (greedy) \) Match the character “)” literally \( Match the character “(” literally P75 Match the characters “P75” literally \) Match the character “)” literally $ Assert position at the end of the string (or before the line break at the end of the string, if any)
来源:https://stackoverflow.com/questions/63283913/how-to-replace-a-value-in-text-file-using-powershell-script