How to replace a string preceded by zero, one or more spaces in PowerShell - powershell

I'm using the .Replace() function to replace line feeds in the file I'm working on with a carriage return and a line feed but I would also like to match any number of spaces preceding the line feed. Can this be done in the same operation using a regular expression?
I've tried various combinations of "\s +*" but none have worked, except with a fixed number of manually typed spaces.
This version works for the one space case:
.Replace(" `n","`r`n")
For example, a file like this:
...end of line one\n
...end of line two \n
would look like:
...end of line one\r\n
...end of line two\r\n

The .Replace() method of the .NET [string] type performs literal string replacements.
By contrast, PowerShell's -replace operator is based on regexes (regular expressions), so it allows you to match a variable number of spaces (including none) with  *:
"...end of line two `n" -replace ' *\n', "`r`n"

Related

Powershell replace command not removing newline

I have text that prints out like this:
mdbAppText_Arr: [0]: The cover is open. {goes to next line here}
Please close the cover. and [1] Backprinter cover open
46
I tried getting rid of the newline after open., and it's still there. Any idea of a better way or fix for what I'm doing? I need to get rid of the newline because it's going to a csv file, and messing up formatting (going to newline there).
This is my code:
$mdbAppText_Arr = $mdbAppText.Split("|")
$mdbAppText_Arr[0].replace("`r",";").replace("`n",";").replace("`t",";").replace("&",";")
#replace newline/carriage return/tab with semicolon
if($alarmIdDef -eq "12-7")
{
Write-Host "mdbAppText_Arr: [0]: $($mdbAppText_Arr[0]) and [1] $($mdbAppText_Arr[1]) "
[byte] $mdbAppText_Arr[0][31]
}
I've been looking at:
replace
replace - this one has a link reference to lookup in the asci table, but it's unclear to me what column the byte equivalent is in the table/link.
I'm using PowerShell 5.1.
-replace is a regex operator, so you need to supply a valid regular expression pattern as the right-hand side operand.
You can replace most newline sequences with a pattern describing a substring consisting of:
an optional carriage return (\r? in regex), followed by
a (non-optional) newline character (\n in regex):
$mdbAppText_Arr = $mdbAppText_Arr -replace '\r?\n'

Powershell Regex Multiline parsing

I am working on building a script that will analyze a configuration file (cisco switch config) and build a report based on certain findings. Sadly- the findings must be recorded on a specific form so this painful path is my only option outside of manual generation of each form.
What I'm trying to do:
Using the following I am attempting to pull the following multi-line expression into PS for evaluation
interface vlan1
no ip address
shutdown
!
I have found multiple sources that point towards one of two options- the first (and simplest) being to load the file into Get-content using the "-raw" switch in order to evaluate the entire file as a single string and then use the "select-string" command to output the specific information that I am looking for.
My basic code looks something like this
if (get-content -path U:\Testing\Test.txt -Raw | select-string -Pattern "(?ms)interface vlan1.*no ip address.*(?!no shutdown)shutdown.*\!" -Quiet)
{
write-host('pass')
}
else
{
write-host('fail')
}
Expected outcome: if the string is true- I will append the finding to a file (that part I have already)
If the configuration does not contain "shutdown" exclusively (without the word no) then it will be annotated as such (again I have that process as well)
Thank you in advance for your assistance- hopefully this is clear and concise.
Further clarity: the script returns false positives/negatives. when running the get-content + select-string outside of the if command- I basically get the -raw output but no match on the string itself, leading me to believe that I am having an issue with the start of line (interface vlan1) and the end line (!)
I have played with the structure of the regex string to try and tease out a solution but I am still a bit vague as to the usage of multi-line output while using select-string.
Since you need to look at the file in full, there's no reason to use the Select-String cmdlet, given that -match, the regular-expression matching operator, works more effectively on strings that are already in memory.
Note: -match only every finds one match (if any); if this is not sufficient, use the [regex]::Matches() .NET method; it is unfortunate that there's no operator for multiple matches; GitHub issue #7867 proposes introducing one, named -matchall.
Your regex is too permissive (greedy) due to use of .* across lines due to the (?s) matching option, so matching happens across multiple blocks.
The following uses a regex without .*, and instead explicitly matches the lines in full, including explicit matching of intervening newlines (\r?\n).[1]
This works with your sample input, but you may need to tweak the regex (omitting the (?s) option makes .* match only intra-line; expressions can be made non-greedy by modifying a duplication symbol with ? (e.g. .*?)).
$re = '(?m)^interface vlan1\r?\nno ip address\r?\n(?!no shutdown)shutdown\r?\n!'
if ((Get-Content U:\Testing\Test.txt -Raw) -match $re) {
# ...
}
Note: The assumption is that there's no need to validate that the trailing ! is the only character on its line; if that is needed, append (?:\r?\n|\z).[2]
[1] This regex matches both common newline formats: CRLF (\r\n, Windows) and LF (\n, Unix).
[2] Unfortunately, use of $ to assert the end of a line (with the (?m) option in effect) may not work if the input uses CRLF (\r\n) newlines, because the $ matches the position of a LF character (\n) only, which means that $ does not match immediately after !, due to the intervening \r.

Remove all text after line with [info]

I am trying to remove all lines of text after a single line of text "[info]" Here is an example:
Top=1266
[info]
name=tod
space=456
number=221,441,111,0
[version]
version=1
I only need the top, the other text will be replaced later on in the script. Here is all that I have tried
$Content -replace '\[Info\]*',''
Only removes the Info line and not anything past that. I have tried to loop, but I can't seem to find the line with a where object search.
What is a quick and easy way to remove all lines of code after a single line of set text?
To make the -replace operator treat it as one string, add (?s) to the pattern.
$Content -replace '(?s)\[Info\].*'
You also needed to match any character so .* works in this case. The second part is optional. Since you're replacing it with nothing you can simply omit it.
Read more about regular expression in powershell
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.1
and operators
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.1

Design Powershell script for find the Numbers which contain file

Everyone help to design the script to find the Numbers which contain file..
For example:
20200514_EE#998501_12.
I need numbers 12 then write to the txt file
the contain will generated different sequence numbers..
For example: #20200514_EE#998501_123.#
so, I need numbers 123 then write to the txt file
How to write the script in Powershell or bat file ?
Very appreciate!
Thanks
Tony
You can do the following as a start. You have not provided enough information/examples to work through any issues you are experiencing.
'#20200514_EE#998501_123.#' -replace '^.*?(\d+)\D*$','$1'
'#20200514_EE#998501_123' -replace '^.*?(\d+)\D*$','$1'
-replace uses regex matching and then replaces with a string and/or matched substitute. ^ is the start of the string. .*? lazily matches all characters. \d+ matches one or more digits in a capture group due to the encapsulating (). \D* matches zero or more non-digits. $ matches the end of the string. For the replacement, $1 is capture group 1, which is what was captured by (\d+).
You can use the .Split() method also in combination with -replace.
'#20200514_EE#998501_123.#'.Split('_')[-1] -replace '\D+$'

powershell -split('') specify a new line

Get-Content $user| Foreach-Object{
$user = $_.Split('=')
New-Variable -Name $user[0] -Value $user[1]}
Im trying to work on a script and have it split a text file into an array, splitting the file based on each new line
What should I change the "=" sign to
It depends on the exact encoding of the textfile, but [Environment]::NewLine usually does the trick.
"This is `r`na string.".Split([Environment]::NewLine)
Output:
This is
a string.
The problem with the String.Split method is that it splits on each character in the given string. Hence, if the text file has CRLF line separators, you will get empty elements.
Better solution, using the -Split operator.
"This is `r`na string." -Split "`r`n" #[Environment]::NewLine, if you prefer
You can use the String.Split method to split on CRLF and not end up with the empty elements by using the Split(String[], StringSplitOptions) method overload.
There are a couple different ways you can use this method to do it.
Option 1
$input.Split([string[]]"`r`n", [StringSplitOptions]::None)
This will split on the combined CRLF (Carriage Return and Line Feed) string represented by `r`n. The [StringSplitOptions]::None option will allow the Split method to return empty elements in the array, but there should not be any if all the lines end with a CRLF.
Option 2
$input.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)
This will split on either a Carriage Return or a Line Feed. So the array will end up with empty elements interspersed with the actual strings. The [StringSplitOptions]::RemoveEmptyEntries option instructs the Split method to not include empty elements.
The answers given so far consider only Windows as the running environment. If your script needs to run in a variety of environments (Linux, Mac and Windows), consider using the following snippet:
$lines = $input.Split(
#("`r`n", "`r", "`n"),
[StringSplitOptions]::None)
There is a simple and unusual way to do this.
$lines = [string[]]$input
This will split $input like:
$input.Split(#("`r`n", "`n"))
This is undocumented at least in docs for Conversions.
Beware, this will not remove empty entries.
And it doesn't work for Carriage Return (\r) line ending at least on Windows.
Experimented in Powershell 7.2.
This article also explains a lot about how it works with carriage return and line ends. https://virot.eu/powershell-and-newlines/
having some issues with additional empty lines and such i found the solution to understanding the issue. Excerpt from virot.eu:
So what makes up a new line. Here comes the tricky part, it depends.
To understand this we need to go to the line feed the character.
Line feed is the ASCII character 10. It in most programming languages
escaped by writing \n, but in powershell it is `n. But Windows is not
content with just one character, Windows also uses carriage return
which is ASCII character 13. Escaped \r. So what is the difference?
Line feed advances the pointer down one row and carriage return
returns it to the left side again. If you store a file in Windows by
default are linebreaks are stored as first a carriage return and then
a line feed (\r\n). When we aren’t using any parameters for the
split() command it will split on all white-space characters, that is
both carriage return, linefeed, tabs and a few more. This is why we
are getting 5 results when there is both carriage return and line
feeds.