Powershell TRIM() is removing extra character - powershell

I'm attempting to remove the "\MOSS2013" instance name from my SQL Server instance "WSFCSQLN1\MOSS2013"
This works:
$primaryReplicaGEN = $wsfcsqln2.AvailabilityGroups.PrimaryReplicaServerName
$primaryReplica = $PrimaryReplicaGEN.TRIM("\GEN")
$primaryReplica shows WSFCSQLN1
$primaryReplicaGEN shows WSFCSQLN1\GEN
This does not work:
$primaryReplicaMOSS2013 = $wsfcsqln1MOSS2013.AvailabilityGroups.PrimaryReplicaServerName
$primaryReplica = $PrimaryReplicaMOSS2013.TRIM("\MOSS2013")
$primaryReplica shows WSFCSQLN
$primaryReplicaMOSS2013 shows WSFCSQLN1\MOSS2013
Notice the replica name is missing the 1 at the end even though I did not choose to trim it. Why is it trimming the 1 for this particular string object? How can I force it to trim the correct characters.

Trim() turns the string argument into a [char[]] and removes any of those characters from both ends of the string.
If you just want to grab the server name, use the -split operator and then discard the instance name:
$ServerName = 'WSFCSQLN1\MOSS2013' -split '\\' |Select-Object -First 1
or
$ServerName,$null = 'WSFCSQLN1\MOSS2013' -split '\\'

well, thats how trim works, it will remove all the occurrences of all the characters you are going to trim which it can get to.
"agababga".Trim("ag")
would return bab not ababga, notice it didn't trim a inside bab as it cannot trim b, if you do:
"agababga".Trim("agb")
you would get nothing (empty string) in response

you can use convertfrom-string too like this
$SplitedVar='WSFCSQLN1\MOSS2013' | ConvertFrom-String -Delimiter "\\" -PropertyNames "Domain", "ServerName"
$SplitedVar.Domain
$SplitedVar.ServerName

I'd use a split call:
$primaryReplica = $PrimaryReplicaGEN.split('\')[0];

Related

Remove everything from string before given variable

I have a string some\string/with/**/special\chars\haha. In variable I hold chars string and I try to remove everything before and including chars so expected output would be \haha
I tried sth like:
$temp = "some\string/with/**/special\chars\haha"
$tmp="chars"
$temp -replace '(?s)^.*$tmp', ''
and
$temp -replace '(?s)^.*$([regex]::Escape($tmp))', ''
but the only thing that works is when I put the string directly into regex condition. Only this example gives expected output:
$temp -replace '(?s)^.*chars', ''
What am I doing wrong?
Edit.:
I need to use variable in regex, because I iterate through multiple strings like this one and not always the part I want to remove has the same string (example: some\string/with/**/special\chars\haha -> \haha; C:\st/h/*/1234\asdf\x -> \x). So in conclusion I have a problem using variable in regex, not with the regex itself as that works as intended when I replace variable with string (as shown above)
Try
$temp = "some\string/with/**/special\chars\haha"
$tmp="chars"
$regex = '(?s)^.*' + $tmp
$temp -replace $regex, ''
Looks like it's because you are using single quotes in your regex instead of double quotes. This means that the variable $tpm isn't being used.
Here is what your code should look like:
$temp = "some\string/with/**/special\chars\haha"
$tmp="chars"
$temp -replace "(?s)^.*$tmp", ''
Your code was using $tmp instead of the actual value inside the $tmp variable.

How can I split a string into an array on every newline?

In my situation, I will have a string that looks like this.
$emailList = "example#mail.com
example2#mail.com
example3#mail.com"
How can I port this into an array with no white-space so it would look like
$emailList = #("example#mail.com","example2#mail.com","example3#mail.com"
Per the comments, if you do this:
($emailList -split '\r?\n').Trim()
It uses -split to separate the list in to an array based on the new line/return charaters and then .Trim() to remove any whitespace either side of each string.
Following this the result is now already an array. However if you explicitly want the output to be as a list of comma separated strings surrounded by double quotes you could then do this:
(($emailList -split '\r?\n').Trim() | ForEach-Object { '"'+$_+'"' }) -Join ','
Which uses ForEach-Object to add quote marks around each entry and then uses -Join to connect them with a ,.
$emailList = "example#mail.com
example2#mail.com
example3#mail.com"
$emailList.Split([Environment]::NewLine,[Stringsplitoptions]::RemoveEmptyEntries).trim()
-split on the left side splits on variable whitespace:
$emailList = -split 'example#mail.com
example2#mail.com
example3#mail.com'
$emailList
example#mail.com
example2#mail.com
example3#mail.com
You can also form an array list this. #() is almost never needed.
$emailList = 'example#mail.com','example2#mail.com','example3#mail.com'
Or as a shortcut (echo is an alias for write-output):
$emailList = echo example#mail.com example2#mail.com example3#mail.com

How can I replace every comma with a space in a text file before a pattern using PowerShell

I have a text file with lines in this format:
FirstName,LastName,SSN,$x.xx,$x.xx,$x.xx
FirstName,MiddleInitial,LastName,SSN,$x.xx,$x.xx,$x.xx
The lines could be in either format. For example:
Joe,Smith,123-45-6789,$150.00,$150.00,$0.00
Jane,F,Doe,987-65-4321,$250.00,$500.00,$0.00
I want to basically turn everything before the SSN into a single field for the name thus:
Joe Smith,123-45-6789,$150.00,$150.00,$0.00
Jane F Doe,987-65-4321,$250.00,$500.00,$0.00
How can I do this using PowerShell? I think I need to use ForEach-Object and at some point replace "," with " ", but I don't know how to specify the pattern. I also don't know how to use a ForEach-Object with a $_.Where so that I can specify the "SkipUntil" mode.
Thanks very much!
Mathias is correct; you want to use the -replace operator, which uses regular expressions. I think this will do what you want:
$string -replace ',(?=.*,\d{3}-\d{2}-\d{4})',' '
The regular expression uses a lookahead (?=) to look for any commas that are followed by any number of any character (. is any character, * is any number of them including 0) that are then followed by a comma immediately followed by a SSN (\d{3}-\d{2}-\d{4}). The concept of "zero-width assertions", such as this lookahead, simply means that it is used to determine the match, but it not actually returned as part of the match.
That's how we're able to match only the commas in the names themselves, and then replace them with a space.
I know it's answered, and neatly so, but I tried to come up with an alternative to using a regex - count the number of commas in a line, then replace either the first one, or the first two, commas in the line.
But strings can't count how many times a character appears in them without using the regex engine(*), and replacements can't be done a specific number of times without using the regex engine(**), so it's not very neat:
$comma = [regex]","
Get-Content data.csv | ForEach {
$numOfCommasToReplace = $comma.Matches($_).Count - 4
$comma.Replace($_, ' ', $numOfCommasToReplace)
} | Out-File data2.csv
Avoiding the regex engine entirely, just for fun, gets me things like this:
Get-Content .\data.csv | ForEach {
$1,$2,$3,$4,$5,$6,$7 = $_ -split ','
if ($7) {"$1 $2 $3,$4,$5,$6,$7"} else {"$1 $2,$3,$4,$5,$6"}
} | Out-File data2.csv
(*) ($line -as [char[]] -eq ',').Count
(**) while ( #counting ) { # split/mangle/join }

How to Split DistinguishedName?

I have a list of folks and their DN from AD (I do not have direct access to that AD). Their DNs are in format:
$DNList = 'CN=Bob Dylan,OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com',
'CN=Ray Charles,OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com',
'CN=Martin Sheen,OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com'
I'd like to make $DNList return the following:
OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com
I decided to turn my comment into an answer:
$DNList | ForEach-Object {
$_ -replace '^.+?(?<!\\),',''
}
Debuggex Demo
This will correctly handle escaped commas that are part of the first component.
We do a non-greedy match for one or more characters at the beginning of the string, then look for a comma that is not preceded by a backslash (so that the dot will match the backslash and comma combination and keep going).
You can remove the first element with a replacement like this:
$DNList -replace '^.*?,(..=.*)$', '$1'
^.*?, is the shortest match from the beginning of the string to a comma.
(..=.*)$ matches the rest of the string (starting with two characters after the comma followed by a = character) and groups them, so that the match can be referenced in the replacement as $1.
You have 7 items per user, comma separated and you want rid of the first one.
So, split each item in the array using commas as the delimiter, return matches 1-6 (0 being the first item that you want to skip), then join with commas again e.g.
$DNList = $DNList|foreach{($_ -split ',')[1..6] -join ','}
If you then enter $DNList it returns
OU=Users,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Contractors,OU=Dept,OU=Agency,OU=NorthState,DC=myworld,DC=com
OU=Users,OU=Dept,OU=Agency,OU=WaySouth,DC=myworld,DC=com
Similar to Grahams answer but removed the hardcoded array values so it will just remove the CN portion without worrying how long the DN is.
$DNList | ForEach-Object{($_ -split "," | Select-Object -Skip 1) -join ","}
Ansgar most likely has a good reason but you can just use regex to remove every before the first comma
$DNList -replace "^.*?,"
Update based on briantist
To maintain a different answer but one that works this regex can still have issues but I doubt these characters will appear in a username
$DNList -replace "^.*?,(?=OU=)"
Regex uses a look ahead to be sure the , is followed by OU=
Similarly you could do this
($DNList | ForEach-Object{($_ -split "(,OU=)" | Select-Object -Skip 1) -join ""}) -replace "^,"

Find and replace at powershell

My textfile looks like this:
-------------------
Set PRGVER="V1.0.12"
Set PRGDIR=C:\PRGSTD\oif_mes\OIFplus
Set PRGEXE=OIFplus.bat
Set PRGTXT=OIFplus
echo %PRGTXT%, %PRGVER%
start "%PRGTXT%" /D%PRGDIR%\%PRGVER%\ %PRGDIR%\%PRGVER%\%PRGEXE%
----------------------
What I wan't to do, edit this file, only change Set PRGVER="V1.0.12" to a new number, like this Set PRGVER=V1.0.13".
When is start the PS Script, I don't know the whole string, the number between "".
I only know, find string variable: Set PRGVER="".
How can I replace only the first value between ""?
Something like this;
$srt = <your text>
$r = $str -replace "PRGVER=`".*`"", "PRGVER=`"your_replace`""
The following should do it. It finds the a line that starts with 'Set PRGVER="V', followed by any number of digits, then a dot, any number of digits, a dot, any number of digits, and ends with '"'. When found, the line is replaced with 'Set PRGVER="V1.0.13"' and the result is saved back to the file.
(Get-Content file.txt) -replace '^Set PRGVER="V\d+\.\d+.\d+"$','Set PRGVER="V1.0.13"' | Out-File file.txt
Following PoSH will replace PRGVER value:
$newValue = "v123.456.789"
gc D:\temp\text | % { $_ -ireplace '(Set PRGVER=)\"([^"]*)\"', ('$1"' + $newValue + '"') };
You using key: Ctrl + H
More information: https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/ise/keyboard-shortcuts-for-the-windows-powershell-ise?view=powershell-7