powershell - get a single word out of a string - powershell

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.

Related

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

Extract string between two special characters in powershell

I need to extract a list with strings that are between two special characters (= and ;).
Below is an example of the file with line types and the needed strings in bold.
File is a quite big one, type is xml.
<type="string">data source=**HOL4624**;integrated sec>
<type="string">data source=**HOL4625**;integrated sec>
I managed to find the lines matching “data source=”, but how to get the name after?
Used code is below.
Get-content regsrvr.txt | select-string -pattern "data source="
Thank you very much!
<RegisteredServers:ConnectionStringWithEncryptedPassword type="string">data source=HOL4624;integrated security=True;pooling=False;multipleactiveresultsets=False;connect timeout=30;encrypt=False;trustservercertificate=False;packet size=4096</RegisteredServers:ConnectionStringWithEncryptedPassword>
<RegisteredServers:ConnectionStringWithEncryptedPassword type="string">data source=HOL4625;integrated security=True;pooling=False;multipleactiveresultsets=False;connect timeout=30;encrypt=False;trustservercertificate=False;packet size=4096</RegisteredServers:ConnectionStringWithEncryptedPassword>
The XML is not valid, so it's not a clean parse, anyway you can use string split with regex match:
$html = #"
<RegisteredServers:ConnectionStringWithEncryptedPassword type="string">data source=HOL4624;integrated security=True;pooling=False;multipleactiveresultsets=False;connect timeout=30;encrypt=False;trustservercertificate=False;packet size=4096</RegisteredServers:ConnectionStringWithEncryptedPassword>
<RegisteredServers:ConnectionStringWithEncryptedPassword type="string">data source=HOL4625;integrated security=True;pooling=False;multipleactiveresultsets=False;connect timeout=30;encrypt=False;trustservercertificate=False;packet size=4096</RegisteredServers:ConnectionStringWithEncryptedPassword>
"#
$html -split '\n' | % {$null = $_ -match 'data source=.*?;';$Matches[0]} |
% {($_ -split '=')[1] -replace ';'}
HOL4624
HOL4625
Since the connectionstring is for SQL Server, let's use .Net's SqlConnectionStringBuilder to do all the work for us. Like so,
# Test data, XML extraction is left as an exercise
$str = 'data source=HOL4624;integrated security=True;pooling=False;multipleactiveresultsets=False;connect timeout=30;encrypt=False;trustservercertificate=False;packet size=4096'
$builder = new-object System.Data.SqlClient.SqlConnectionStringBuilder($str)
# Check some parameters
$builder.DataSource
HOL4624
$builder.IntegratedSecurity
True
You can expand your try at using Select-String with a better use of regex. Also, you don't need to use Get-Content first. Instead you can use the -Path parameter of Select-String.
The following Code will read the given file and return the value between the = and ;:
(Select-String -Path "regsrvr.txt" -pattern "(?:data source=)(.*?)(?:;)").Matches | % {$_.groups[1].Value}
Pattern Explanation (RegEx):
You can use -pattern to capture an String given a matching RegEx. The Regex can be describe as such:
(?: opens an non-capturing Group
data source= matches the charactes data source=
) closes the non-capturing Group
(.*?) matches any amount of characters and saves them in a Group. The ? is the lazy operator. This will stop the matching part at the first occurence of the following group (in this case the ;).
(?:;) is the final non-capturing Group for the closing ;
Structuring the Output
Select-String returns a Microsoft.PowerShell.Commands.MatchInfo-Object.
You can find the matched Strings (the whole String and all captured groups) in there. We can also loop through this Output and return the Value of the captured Groups: | % {$_.groups[1].Value}
% is just an Alias for For-Each.
For more Informations look at the Select-String-Documentation and try your luck with some RegEx.

Powershell replace between start and end

I need to replace everything between two points.
$import = Get-Content C:\bookmarks.html
$newbody = Get-Content C:\newbookmarks.html
$remove = '(?<=<DT><H3 ADD_DATE=""1544626193"" LAST_MODIFIED=""154649885"">Import-IE</H3>).*?(?=</DL>)'
$import | %{$_.replace($remove,"$newbody")}
My problem is to get all content between start:
<DT><H3 ADD_DATE=""1544626193"" LAST_MODIFIED=""154649885"">Import-IE</H3>
and the end:
</DL>
incl multiple lines
Example html:
<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>
<DL><p>
<DT>golem.de
<DT>heise online
</DL>
Regards
A couple of changes needed to make this work:
One big multiline string
Since you want to do a replace over multiple lines, we need to makes sure all the lines are contained in the same string, so let's start with that - we can use the -Raw parameter switch with Get-Content:
$import = Get-Content C:\bookmarks.html -Raw
Exact pattern matching in regex
Next up we have the regex pattern itself - there's a few discrepancies between that and the sample content you've shown:
LAST_MODIFIED=""154649885"" # pattern has nested double-quotes and only one 5 at the end
LAST_MODIFIED="1546498855" # input uses just one pair of double-quotes and value has two 5's at the end
So let's fix that, and make sure the input string we're looking for is properly escaped while we're at it:
$remove = "(?<=$([regex]::Escape('<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>'))).*?(?=</DL>)"
String.Replace doesn't support regex
Then, we'll have to abandon the String.Replace() method that you're currently using - because it doesn't actually support regex - so we'll use the -replace operator instead:
$import -replace $remove,"$newbody"
Use -replace in SingleLine mode
The only thing we need now, is to instruct the regex parser to treat the input in SingleLine mode - so that .*? will capture newlines as well. This is super easy though, we just add an options flag s at the start of the regex pattern:
$import -replace "(?s)$remove","$newbody"
And that's it :)
$import = Get-Content C:\bookmarks.html -Raw
$newbody = Get-Content C:\newbookmarks.html
$remove = "(?<=$([regex]::Escape('<DT><H3 ADD_DATE="1544626193" LAST_MODIFIED="1546498855">Import-IE</H3>'))).*?(?=</DL>)"
$import -replace "(?s)$remove","$newbody"

using powershell like awk to get the console user

I basically want to use powershell and get the console user like
"query session | findstr console | awk '{print $2}'"
but not using awk, but I can't get it to work.
$out = query session | findstr console # good
$consoleuser = $out.split('\s+')[1] # doesn't work
$out looks something like:
>console joe 2 Active
$consoleuser ends up being:
ole joe 2 Active
As others have suggested try the following
$out = query session | findstr console
$consoleuser = $($out -split('\s+'))[1]
Or you could try
$consoleuser = $ENV:username
.Split() is a .Net string method, it doesn't use regexes. -split is the PowerShell operator and uses regexes.
And calling out to findstr is usable, but there's no need to leave PS to use it. e.g.
$out = query session | Where {$_ -match 'console'}
$consoleuser = ($out -split '\s+')[1]
((query session) -match 'console' -split '\s+')[1]
To complement TessellatingHeckler's helpful answer with a further optimization (but note that armorall171's helpful recommendation to simply use $env:USERNAME may be all you need):
(-split ((query session) -match '^>console'))[1]
Output from external command query session is returned as an array of strings by PowerShell, and the -match operator filters that array down to only the matching elements (just 1 line in this case).
The -split operator has a unary form whose behavior is similar to awk's default field-parsing behavior:
It splits the input into array elements by runs of whitespace, ignoring leading and trailing whitespace.
Example:
> -split " ab `t `t cde `n `n efgh "
ab
cde
efgh
Try
($out -Split '\s+')[1]
More useful stuff here

Change specific part of a string

I've got a .txt-File with some text in it:
Property;Value
PKG_GUID;"939de9ec-c9ac-4e03-8bef-7b7ab99bff74"
PKG_NAME;"WinBasics"
PKG_RELATED_TICKET;""
PKG_CUSTOMER_DNS_SERVERS;"12314.1231
PKG_CUSTOMER_SEARCH_DOMAINS;"ms.com"
PKG_JOIN_EXISTING_DOMAIN;"True"
PKG_DOMAINJOIN_DOMAIN;"ms.com"
PKG_DOMAINJOIN_USER;"mdoe"
PKG_DOMAINJOIN_PASSWD;"*******"
So now, is there a way to replace those *'s with e.g. numbers or sth. ?
If so, may you tell me how to do it?
Much like Rahul I would use RegEx as well. Considering the application I'd run Get-Content through a ForEach loop, and replace text as needed on a line-by-line basis.
Get-Content C:\Path\To\File.txt | ForEach{$_ -replace "(PKG_DOMAINJOIN_PASSWD;`")([^`"]+?)(`")", "`${1}12345678`$3"}
That would output:
Property;Value
PKG_GUID;"939de9ec-c9ac-4e03-8bef-7b7ab99bff74"
PKG_NAME;"WinBasics"
PKG_RELATED_TICKET;""
PKG_CUSTOMER_DNS_SERVERS;"12314.1231
PKG_CUSTOMER_SEARCH_DOMAINS;"ms.com"
PKG_JOIN_EXISTING_DOMAIN;"True"
PKG_DOMAINJOIN_DOMAIN;"ms.com"
PKG_DOMAINJOIN_USER;"mdoe"
PKG_DOMAINJOIN_PASSWD;"12345678"
On second thought, I don't know if I'd do that. I might import it as a CSV, update the property, and export the CSV again.
Import-CSV C:\Path\To\File.txt -Delimiter ";" |%{if($_.Property -eq "PKG_DOMAINJOIN_PASSWD"){$_.value = "12345678";$_}else{$_}|export-csv c:\path\to\newfile.txt -delimiter ";" -notype
If You are using Powershell V2.0 (Hopefully) you can try something like below. gc is short hand for get-content commandlet.
(gc D:\SO_Test\test.txt) -replace '\*+','12345678'
With this the resultant data would be as below (notice the last line)
Property;Value
PKG_GUID;"939de9ec-c9ac-4e03-8bef-7b7ab99bff74"
<Rest of the lines here>
PKG_DOMAINJOIN_USER;"mdoe"
PKG_DOMAINJOIN_PASSWD;"12345678" <-- Notice here; *'s changed to numbers
Rahul's answer was good, I just wanted to mention that *+ will replace all instances of a single * character or more, so it would match any other place there is at least one star. If what you posted is all you would ever expect for you sample data though this would be fine.
You could alter the regex match to make it more specific if it was needed by changing it to something like
\*{3,0}
which would match 3 or more stars, or very specific would be
(?<=")\*{3,}(?=")
which would replace 3 or more stars which are surrounded by double quotes.
Here's a function that uses regex lookahead and lookbehind zero-length assertions to replace named parameters in a string similar to your example:
function replace-x( $string, $name, $value ) {
$regex = "(?<=$([regex]::Escape($name));`").*(?=`")"
$string -replace $regex, $value
}
Its reusable for different settings in your file, e.g:
$settings = get-content $filename
$settings = replace-x $settings PKG_DOMAINJOIN_USER foo
$settings = replace-x $settings PKG_DOMAINJOIN_PASSWD bar