2

I want to delete a complete line which contains a special word in a single .csv file in a powershell script.

I already found working code, that deletes the specific line, but writes all other lines into the first line. This shouldn't happen, because I linked the csv-file with an ms access table.

    $user = 'User2'
    $file = Get-Content c:\datei.txt
    $newLine = ""

    foreach($line in $file){

        if($line -match $User){
         }else{
            $newLine += $line
        }
    }
    $newLine | Out-File c:\datei.txt

The file looks like this, but with more data and lines:

User;computer;screen1;screen2;printer
User1;bla;bla;;bla
User2;bla;bla;bla;bla
User3;bla;bla;bla;bla

After running the code:

User;computer;screen1;screen2;printerUser1;bla;bla;;blaUser3;bla;bla;bla;bla

I use Powershell 5.1.x on Windows 7

2 Answers 2

6

It happens because you're doing string concatenation.

$newLine = ""
$newLine += $line

# result is exactly how it looks,  
# "" -> "line1" -> "line1line2" -> "line1line2line3" ...

The straightforward fix is to use an array:

$newLine = @()
$newLine += $line

# result is adding lines to an array  
# @() -> @("line1") -> @("line1","line2") -> @("line1","line2","line3") ...

but the proper PowerShell way is not to do that at all, and to stream the file through your code and out into another file:

$user = 'User2'
$file = Get-Content c:\datei.txt

foreach($line in $file){

    if($line -match $User){
     }else{
        $line   # send the line to the output pipeline
    }

} | Out-File c:\datei.txt

But you can invert the test -match to -notmatch and get rid of the empty {} part.

$user = 'User2'
$file = Get-Content c:\datei.txt

foreach($line in $file){

    if($line -notmatch $User){
        $line   # send the line to the output pipeline
    }

} | Out-File c:\datei.txt

And you can get rid of temporarily storing the file content:

$user = 'User2'
Get-Content c:\datei.txt | ForEach-Object {

    if ($_ -notmatch $User){
        $line   # send the line to the output pipeline
    }

} | Out-File c:\datei.txt

But then it's just acting as a filter, and you can change foreach-object / if() {} for a where-object filter:

$user = 'User2'
Get-Content c:\datei.txt | Where-Object {

    $_ -notmatch $User

} | Out-File c:\datei.txt

And then change Out-file for Set-Content (the pairing is get-content/set-content, and it gives more control over output encoding if you need it):

$user = 'User2'

Get-Content c:\datei.txt | 
    Where-Object { $_ -notmatch $User } | 
    Set-Content c:\datei.txt
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. I tried your last suggestion and it also worked. i only had to add brackets, because it says the file was already in use ` (Get-Content c:\datei.txt | Where-Object { $_ -notmatch $User }) | Set-Content c:\datei.txt `
Good catch, I forgot about that happening when overwriting the same file! That makes it a bit uglier, and you may as well do $lines = get-content c:\datei.txt then $lines | where-object {...} | set-content .. really.
0

You need to add a 'newline' to the end of each line of text. Change this line:

$newLine += $line

to:

$newLine += "$line`r`n"

1 Comment

It works, thank you. I was sure, that this `n or something similar was missing somewhere in this line. But i didn't knew, that I have to place this into "".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.