Remove special characters from text file in Windows - powershell

I want to output text from a text file in Windows script like you can in Linux with grep:
grep -ve ^# -ve '^;' -ve ^$ /name of file.
I haven't had much success finding a solution. I am trying to use Powershell with little experience using it.

Use Select-String in place of grep:
Select-String -Path 'path/to/file' -Pattern '^[#;]|^$' -NotMatch
Select-String will output a Match object, if you just want to matched strings, grab the Line property:
Select-String ... |Select -Expand Line
Starting with PowerShell 7.0 you can also use the -Raw switch to have Select-String return only the matched strings and nothing else:
Select-String ... -Raw

This comes close. You can have an array of patterns seperated by commas. Just like in bash, the semicolon has to be quoted, because it means "end of statement" in powershell. The command avoids lines that start with "#", ";", or are blank.
'# comment',
'; semicolon',
'',
'one',
'two',
'three' | select-string ^#, '^;', ^$ -notmatch
one
two
three

This is what I used to output I was after; get-childitem zabbix_agentd.conf | select-string -pattern '^[#;]|^$' -notmatch
This is what I was after without all the lines that are commented out and spaces.
zabbix_agentd.conf:24:LogFile=C:\Program Files\Zabbix Agent\zabbix_agentd.log
zabbix_agentd.conf:88:Server=10.0.0.22
zabbix_agentd.conf:130:ServerActive=10.0.0.22
zabbix_agentd.conf:141:Hostname=RED-DOUG
zabbix_agentd.conf:257:Include=C:\Program Files\Zabbix Agent\zabbix_agentd.conf.d\
Thank you for the help, Doug

Related

Powershell -Replace command and escaping characters

I need to replace some strings multiple text files. I am running into an issue with the following string though. I tried escaping with a backtick ` before any special characters, but no luck, or maybe the backtick isn't in the right place.
I want to replace
Signal\s+:\s+',''
with
Signal\s+:\s+','';if (!`$signal) {`$signal='n/a'}
This is the string in the command that i am having a problem finding --> Signal\s+:\s+',''
Here is the powershell command i am using..
Get-ChildItem "f:\temp\*.ps1" | ForEach-Object -Process {(Get-Content $_) -Replace "Signal\s+:\s+',''" , "Signal\s+:\s+','';if (!`$signal) {`$signal='n/a'}" | Set-Content $_}
thank you
i just needed to escape the \ in the replace text.. thats all
-Replace "Signal\\s\+:\\s\+',''"
thanks

What's equation of `grep -Ern` in PowerShell?

I like to search string in all files with command grep -Ern on Bash, but what's equation on Windows PowerShell?
I've read alot about Select-String but I can't make it work as I expect, how should I write the params?
-Ern option stands for
Interpret PATTERNS(In this case Vue) as extended regular expressions(-E)
Read all files under each directory, recursively(-r)
Prefix each line of output with the 1-based line number
within its input file.(-n)
In PowerShell, You can construct the same pattern using the Get-ChildItem and Select-String Cmdlets
Get-ChildItem -path $your_path -Recurse | Select-String -Pattern "pattern"
-Recurse option is to get the items in the specified locations and in all child items of the locations.(equivalent to -r for grep)
Select-String automatically treat -Pattern "pattern" as regular expression(equivalent to -E for grep)
By default, Select-String finds the first match in each line and, for each match, it displays the file name, line number, and all text in the line containing the match(equivalent to -n for grep)

How to replace a newline at the start of a txt file with powershell

I have tried a lot, but I cannot seem to replace the new line at the start of a txt file.
So my txt file looks like this:
I just want to remove the first newline character, but everything I try does not work:
Replace ``n`r, replace \n\r or any combination of these.
Try
(Get-Content -Path 'YourFile.txt' -Raw).TrimStart() | Set-Content -Path 'YourFile.txt' -Force
Or
(Get-Content -Path 'YourFile.txt' -Raw) -replace '^\s+' | Set-Content -Path 'YourFile.txt' -Force
Explanation:
The above removes all whitespace (tabs, spaces, newlines) from the top of the text, as it is impossible to see from the image if other whitespace characters are in that line or not.
If you are sure there is just the one newline, in your case \r\n won't work, because the file uses Unix newlines (\n only).
Better is to replace using ^\r?\n. The ^ anchors at the beginning of the text. The ? reads zero or one on the CR character \r
This would replace all blank lines. The parentheses make sure the first command finishes first if you're writing to the same file.
(get-content file.txt) | where { $_ } | set-content file.txt
Or this way, the filename goes first.
set-content file.txt (get-content file.txt).where{$_}
A different approach
( Get-Content -Tail ( ( Get-Content testfile1 ).count-1 ) testfile1 ) | Set-Content testfile1
Count the number of lines in the file and then take one off the total. Use that to tail the file and write the output back to the file.
If you are certain that there will be an empty line (or you want to ignore it) you can use Skip.
Get-Content -Path 'YourFile.txt' | select -Skip 1 | Set-Content -Path 'YourFile.txt' -Force

Find Carriage Returns in Files Using Powershell

I want to see all the instances of files containing the Windows-style crlf instead of Unix-style lf in a set of files. Here's what I have so far:
sls -Path src/*.cs -Pattern "`r`n" | group Path | select name
This works if I search for any normal text, but it's not finding the carriage returns, even though (according to everything I can find online) that's the proper Powershell escape sequence for carriage returns and newlines. For the record \r\n doesn't work either.
sls (an alias for Select-String) works line by line, so it's already processing (consuming) the line breaks during the file reading process before it gets to the regex matching.
Use something that reads the entire file, and then look for it:
Get-ChildItem -Path src/*.cs | ForEach-Object {
$contents = [System.IO.File]::ReadAllText($_.FullName)
if ($contents -cmatch '\r\n') {
$_
}
} | Group-Object Directory | Select-Object Name
\r\n is used here instead of the backticks because you're escaping them for the regex engine, not for powershell.

Powershell magnling ascii text

I'm getting extra characters and lines when trying to modify hosts files. For example, this select string does not take anything out, but the two files are different:
get-content -Encoding ascii C:\Windows\system32\drivers\etc\hosts |
select-string -Encoding ascii -notmatch "thereisnolinelikethis" |
out-file -Encoding ascii c:\temp\testfile
PS C:\temp> (get-filehash C:\windows\system32\drivers\etc\hosts).hash
C54C246D2941F02083B85CE2774D271BD574F905BABE030CC1BB41A479A9420E
PS C:\temp> (Get-FileHash C:\temp\testfile).hash
AC6A1134C0892AD3C5530E58759A09C73D8E0E818EC867C9203B9B54E4B83566
I can confirm that your commands do inexplicably result in extra line breaks in the output file, in the start and in the end. Powershell also converts the tabs in the original file into four spaces instead.
While I cannot explain why, these commands do the same thing without these issues:
Try this code instead:
Get-Content -Path C:\Windows\System32\drivers\etc\hosts -Encoding Ascii |
Where-Object { -not $_.Contains("thereisnolinelikethis") } |
Out-File -FilePath "c:\temp\testfile" -Encoding Ascii
I think this is more of an issue with PowerShell's F&O (formatting & output) engine. Keep in mind that Select-String outputs a rich object called MatchInfo. When that object reaches the end of the output it needs to be rendered to a string. I think it is that rendering/formatting that injects the extra line. One of the properties on MatchInfo is the line that was matched (or notmatched). If you pass just the Line property down the pipe, it seems to work better (hashes match):
Get-Content C:\Windows\system32\drivers\etc\hosts |
Select-String -notmatch "thereisnolinelikethis" |
Foreach {$_.Line} |
Out-File -Encoding ascii c:\temp\testfile
BTW you only need to specify ASCII encoding when outputting back to the file. Everywhere else in PowerShell, just let the string flow as Unicode.
All that said, I would use Where-Object instead of Select-String for this scenario. Where-Object is a filtering command which is what you want. Select-String takes input of one form (string) and converts it to a different object (MatchInfo).
Out-File adds a trailing NewLine ("`r`n") to the testfile file.
C:\Windows\System32\drivers\etc\hosts does not contain a trailing newline out of the box, which is why you get a different FileHash
If you open the files with a StreamReader, you'll see that the underlying stream differs in length (due to the trailing newline in the new file):
PS C:\> $Hosts = [System.IO.StreamReader]"C:\Windows\System32\drivers\etc\hosts"
PS C:\> $Tests = [System.IO.StreamReader]"C:\temp\testfile"
PS C:\> $Hosts.BaseStream.Length
822
PS C:\> $Tests.BaseStream.Length
824
PS C:\> $Tests.BaseStream.Position = 822; $Tests.Read(); $Tests.Read()
13
10
ASCII characters 13 (0x0D) and 10 (0x0A) correspond to [System.Environment]::NewLine or CR+LF