Reputation: 355
I check a file for lines where a char in a special position is missing. If the char is missing, I insert it in that exact location. Now I want to write that new line with that extra char over the old line into the file. For example I have the following in the file:
"C:\\path\test\test"
"C:\\path\test\test2\"
"C:\\path\test\test3\"
After I run my short script, I want it to look like:
"C:\path\test\test\"
"C:\path\test\test2\"
"C:\path\test\test3\"
I try to accomplish that using this little loop:
$content = Get-Content C:\path\to\file.txt
foreach ($line in $content)
{
if($line[-25] -ne '\') {
$test = $line -replace '(?<!\\)(?=.{24}$)', '\' | Set-Content C:\path\to\file.txt
}
else {
continue
}
}
That code does insert me the char at the correct position. But in the end only line one is in the file, instead of all three lines. I think I am close, but just started with powershell.
Upvotes: 1
Views: 1321
Reputation: 9266
As @briantist points out, you need to move the Set-Content
outside the for loop to set the entire file at once. Inside the for loop, there is no need for character counting, though. And I find it is better to use the system APIs to work with paths rather than try to write a regex.
Get-Content $inputFileName | Foreach-Object {
# Strip quotes
$line = $_ -replace '"',''
# Add trailing backslash if needed
$line += '\'
# Call .NET GetFullPath to normalize. This removes double backslashes
# and resolves relative paths if needed.
$line = [System.IO.Path]::GetFullPath($line)
# Add quotes back, and output string
'"' + $line + '"'
} | Set-Content $outputFileName
Or, in much condensed form
gc $inputFile | % { [io.path]::GetFullPath((($_+'\') -replace '"','')) } | sc $outputFile
Upvotes: 2
Reputation: 47792
Set-Content
replaces all the content in a file with the input values. You're calling it independently on each iteration of the loop, when what you really want is to call it with all the results of the loop.
There are many ways to change it, but I would consider replacing foreach
with ForEach-Object
, and piping the result into Set-Content
:
Get-Content C:\path\to\file.txt |
ForEach-Object -Process {
$line = $_
if($line[-25] -ne '\') {
$line -replace '(?<!\\)(?=.{24}$)', '\'
} else {
$line
}
} | Set-Content C:\path\to\file.txt
Upvotes: 2