Replace character from link with powershell - powershell

I would like replace ? in
"EquipmentInfo["?"] = "<iframe src='http://bing.fr'></iframe>";"
by a variable.
I tried this:
(get-content C:\word.txt) -replace '?', '$obj' | Set-Content C:\word.txt

I would use a positive lookbehind to ensure you find the right question mark. Also you have to use double quote on your replacement since you want to replace a variable:
(get-content C:\word.txt -raw) -replace '(?<=EquipmentInfo\[")\?', "$obj" | Set-Content C:\word.txt
Regex used:
(?<=EquipmentInfo\[")\?

This answer explains the original problem.
jisaak's helpful answer provides a comprehensive solution.
The -replace operator takes a regular expression as the first operand on the RHS, in which ? is a so-called metacharacter with special meaning.
Thus, to use a literal ?, you must escape it, using \:
(get-content C:\word.txt) -replace '\?', $obj
Note: Do not use '...' around $obj, unless you want literal string $obj; generally, to reference variables inside strings you must use "...", but that's not necessary here.
A simple example with a literal:
'Right?' -replace '\?', '!' # -> 'Right!'

Related

powershell - get a single word out of a string

I have a string:
<UserInputs><UserInput Question="Groupname" Answer="<Values Count="1"><Value DisplayName="AllHummanresources" Id="af05c5d3-2312-c897-8439-08979d4d0a49" /></Values>" Type="System.SupportingItem.PortalControl.InstancePicker" /><UserInput Question="Ausgabe" Answer="Namen" Type="richtext" /></UserInputs>
I want to trim the string to get as result "AllHummanresources". So I need the word between DisplayName=" and " .
How can I achieve this goal?
I did not find a fitting example in the net :(
greetings
You can use Select-String Cmdlet along with regex.
$result = $your_string | Select-String -Pattern "DisplayName="(.*?)""
If the match is successful you can access the group by
Write-Host $result.Matches.Groups[1].Value
You could use the -replace operator so that you omit everything apart from that string.
$string -replace '.+(?:DisplayName=")(.*?)&quot.+', '$1'
Granted this is only as good as the consistency of your input string.

Wanted to get middle text from PSObject in Powershell

I have a PSObject which contains the following Values
AZREUS/MYVM-0.mydomain.com
AZREUS/MYVM-1.mydomain.com
I need only the VM name stored in a new PS-Object, how can I do that.
The list should return like below.
MYVM-0
MYVM-1
a simple way can be to use -replace operator:
$list = #('AZREUS/MYVM-0.mydomain.com','AZREUS/MYVM-1.mydomain.com')
$list -replace 'AZREUS/'-replace '\.mydomain\.com'
YannCha's answer is an efficient answer if your strings always begin with AZREUS/ and end with .mydomain.com. You can use a single -replace to get the desired result.
$obj = 'AZREUS/MYVM-0.mydomain.com','AZREUS/MYVM-1.mydomain.com'
$obj -replace '^AZREUS/(.*)\.mydomain\.com$','$1'
$1 represents capture group 1, which was created by the first parentheses grouping (). It contains .* contents. See Regex for regex explanation.
Taking the same approach further dynamically, you can use pattern matching. This removes all beginning characters including the first /. Then removes the first . and all characters after it.
$obj -replace '^.*/(.*?)\..*$','$1'
See Regex for regex explanation.
Note that if your object items are not strings, they will need to support being converted to strings or you will have to do that yourself before applying -replace.
Or using -match. Do them one at a time.
'AZREUS/MYVM-0.mydomain.com' -match 'AZREUS/(.*).mydomain.com' > $null; $matches[1]
MYVM-0
'AZREUS/MYVM-1.mydomain.com' -match 'AZREUS/(.*).mydomain.com' > $null; $matches[1]
MYVM-1

Split & Trim in a single step

In PS 5.0 I can split and trim a string in a single line, like this
$string = 'One, Two, Three'
$array = ($string.Split(',')).Trim()
But that fails in PS 2.0. I can of course do a foreach to trim each item, or replace ', ' with ',' before doing the split, but I wonder if there is a more elegant approach that works in all versions of PowerShell?
Failing that, the replace seems like the best approach to address all versions with a single code base.
TheMadTechnician has provided the crucial pointer in a comment on the question:
Use the -split operator, which works the same in PSv2: It expects a regular expression (regex) as the separator, allowing for more sophisticated tokenizing than the [string] type's .Split() method, which operates on literals:
PS> 'One, Two, Three' -split ',\s*' | ForEach-Object { "[$_]" }
[One]
[Two]
[Three]
Regex ,\s* splits the input string by a comma followed by zero or more (*) whitespace characters (\s).
In fact, choosing -split over .Split() is advisable in general, even in later PowerShell versions.
However, to be fully equivalent to the .Trim()-based solution in the question, trimming of leading and trailing whitespace is needed too:
PS> ' One, Two,Three ' -split ',' -replace '^\s+|\s+$' | ForEach-Object { "[$_]" }
[One]
[Two]
[Three]
-replace '^\s+|\s+$' removes the leading and trailing whitespace from each token resulting from the split: | specifies an alternation so that the subexpressions on either side of it are considered a match; ^\s+, matches leading whitespace, \s+$ matches trailing whitespace; \s+ represents a non-empty (one or more, +) run of whitespace characters; for more information about the -replace operator, see this answer.
(In PSv3+, you could simplify to (' One, Two,Three ' -split ',').Trim() or use the solution from the question.
To also weed out empty / all-whitespace elements, append -ne '')
As for why ('One, Two, Three'.Split(',')).Trim() doesn't work in PSv2: The .Split() method returns an array of tokens, and invoking the .Trim() method on that array - as opposed to its elements - isn't supported in PSv2.
In PSv3+, the .Trim() method call is implicitly "forwarded" to the elements of the resulting array, resulting in the desired trimming of the individual tokens - this feature is called member-access enumeration.
I don't have PS 2.0 but you might try something like
$string = 'One, Two, Three'
$array = ($string.Split(',') | % { $_.Trim() })
and see if that suits. This is probably less help for you but for future readers who have moved to future versions you can use the #Requires statement. See help about_Requires to determine if your platforms supports this feature.

How to -replace continuous special characters?

In PowerShell when trying to replace
"Columnname1||colunnname2||kjhsadjhj|kjsad" -replace "[||]", "','"
above command is doing
"Columnname1','','colunnname2','','kjhsadjhj','kjsad"
but I'd like to replace the exact match like below
"Columnname1','colunnname2','kjhsadjhj|kjsad"
Your code doesn't do what you want because your search pattern defines a character class. Square brackets in a regular expression will match exactly one occurrence of any of the enclosed characters, even if you specify a character multiple times. [||] will thus match exatly one | character.
Since you apparently don't actually want to use a regular expression match I'd recommend doing a normal string replacement via the Replace() method rather than a regular expression replacement via the -replace operator:
"Columnname1||colunnname2||kjhsadjhj|kjsad".Replace('||', "','")
If you want to stick with a regular expression replacement you must specify two literal | characters, either by escaping them, as PetSerAl suggested
"Columnname1||colunnname2||kjhsadjhj|kjsad" -replace '\|\|', "','"
or by putting each of them in its own character class
"Columnname1||colunnname2||kjhsadjhj|kjsad" -replace '[|][|]', "','"
The regex pattern [||] means "1 of | or one of |"
Change it to \|{2} to match two consecutive pipes:
"Columnname1||colunnname2||kjhsadjhj|kjsad" -replace "\|{2}", "','"
Just in case your end result should be:
'Columnname1','colunnname2','kjhsadjhj|kjsad'
$string = '"Columnname1||colunnname2||kjhsadjhj|kjsad"'
$string
$String = $string -replace '^"|"$',"'" -replace '\|{2}',"','"
$string
Sample output:
"Columnname1||colunnname2||kjhsadjhj|kjsad"
'Columnname1','colunnname2','kjhsadjhj|kjsad'

How do I match "|" in a regular expression in PowerShell?

I want to use a regular expression to filter out if a string contains one of "&" or "|" or "=". I tried:
$compareRegex = [String]::Join("|", #("&","|", "="));
"mydfa" -match $compareStr
PowerShell prints "True". This is not what I wanted, and it seems "|" itself has confused PowerShell for a matching. How do I fix it?
#Kayasax answer would do in this case (thus +1), just wanted to suggest more general solution.
First of all: you are not using the pattern that you've just created. I suspect $compareStr is $null, thus it will match anything.
To the point: if you want to create pattern that will match characters/strings and you can't predict if any of them will be/contain special character or not, just use [regex]::Escape() for any item you want to match against:
$patternList = "&","|", "=" | ForEach-Object { [regex]::Escape($_) }
$compareRegex = $patternList -join '|'
"mydfa" -match $compareRegex
In such a case input can be dynamic, and you won't end up with pattern that matches anything.
The | has a special meaning in regular expressions. Alternations (lists of alternative matches) are separated by this character. For instance, the expression
a|b|c
would match either a or b or c.
For matching a literal | you need to escape it with backslash (\|) or put it in a character class ([|]), so your expression should look like this:
"mydfa" -match "\||&|="
or like this:
"mydfa" -match "[|&=]"