PowerShell split method on string value - powershell

I'm trying to grab a value from a string within my PowerShell script.
The string can come like this:
$TargetOU = "OU=Company Users,OU=Company,OU=Organisation Users,DC=domain,DC=local"
or like this:
$TargetOU = "OU=Company,OU=Organisation Users,DC=domain,DC=local"
Using the following will return "Company" in the first example but "Company,OU" in the second. How Can I modify this to provide just "Company" in both instances?
$TargetOU.Split('= ')[1]

You can achieve this by adding a , to the characters in your split method.
This is because you split your string at every char given to the split method.
Your first string splits to:
OU
Company
Users,OU
Company,OU
Organisation
Users,DC
domain,DC
local
while your second string splits to:
OU
Company,OU
Organisation
Users,DC
domain,DC
local
When using $TargetOU.Split('= ,') instead your second string will split to:
OU
Company
OU
Organisation
Users
DC
domain
DC
local
where the element with index 1 is only "Company", not "Company,OU"

Try this. Given your examples of input this returns "Company" every time.
What it does: saves your split in a variable and checks if that variable contains a comma, as it would if "OU=Company,OU=Organisation Users,DC=domain,DC=local" was your input. If true, split that again at the comma and save the first part in a variable. I used the same variable name as with the first split, since I assume you want to do the same thing with the result later in your script, regardless of how the input looks.
$SplitTargetOU = $TargetOU.Split('= ')[1]
if ($SplitTargetOU -like '*,*')
{
$SplitTargetOU = $SplitTargetOU.Split(',')[0]
}
EDIT: J. Bergmann's answer was a little simpler. Nice one. :)

This answer doesn't work for me. The split method is not treating the characters as a character array. To fix it, I have to explicitly cast it:
"OU=Company Users,OU=Company,OU=Organisation Users,
DC=domain,DC=local".Split('= ,')
returns
OU=Company Users,OU=Company,OU=Organisation Users,DC=domain,DC=local
but
"OU=Company Users,OU=Company,OU=Organisation Users,
DC=domain,DC=local".Split([char[]]'= ,')
returns
OU
Company
Users
OU
Company
OU
Organisation
Users
DC
domain
DC
local

Related

Add-DnsServerResourceRecord with multiple lines of descriptive text

I'm trying to add multiple strings to the -DescriptiveText property of a single resource record using the command as shown in the docs here:
# a,b,c,d in the following are different items separated by `r`n
Add-DNSServerResourceRecord -DescriptiveText "a`r`nb`r`nc`r`nd" -Name "identifier" -Txt -ZoneName $ZONE -ZoneScope $ZONE_SCOPE -TimeToLive 0:1:0:0
I know the expected return value of another command that retrieves this data results in the following:
TXT
"a"
"b"
"c"
"d"
However the above returns the following which doesn't work
TXT
"a
b
c
d"
I have tried other methods as follows including:
Trying arrays like "a","b","c","d" as referenced in the accepted answer here which errored
Other methods of formatting the string to match the expected output involving adding missing quotes marks to try and align it with the expected return value
Tried calling the command with each individual part which made multiple records with the required data but didn't work as it needs to be in one record
Any advice on how to do it would be appreciated. Thanks :)
Txt records can have multiple strings and/or multiline strings. It looks like your other command is expecting the former.
Unfortunately, the Add-DnsServerResourceRecord cmdlet only accepts a single string for the DescriptiveText. `r`n only adds a newline to that single string, which is why your tool isn't processing them as separate entries.
Instead, use dnscmd:
dnscmd.exe servername /recordadd example.com identifier TXT "a" "b" "c"
A similar annoyance is that Get-DnsServerResourceRecord will only return the first string of a text record as well.

How to identify a character in a string?

I am trying to write a Powershell code to identify a string with a specific character from a filename from multiple files.
An example of a filename
20190902091031_202401192_50760_54206_6401.pdf
$Variable = $Filename.Substring(15,9)
Results:
202401192 (this is what I am after)
However in some instances the filename will be like below
20190902091031_20240119_50760_54206_6401.pdf
$Variable = $Filename.Substring(15,9)
Results:
20240119_ (this is NOT what I am after)
I am trying to find a code to identify the 9th character,
IF the 9th character = "_"
THEN Set
$Variable = $Filename.Substring(15,8)
Results:
20240119
All credit to TheMadTechnician who beat me to the punch with this answer.
To expand on the technique a bit, use the split method or operator to split a string every time a certain character shows up. Your data is separated by the underscore character, so is a perfect example of using this technique. By using either of the following:
$FileName.Split('_')
$FileName -split '_'
You can turn your long string into an array of shorter strings, each containing one of the parts of your original string. Since you want the 2nd one, you use the array descriptor [1] (0 is 1st) and you're done.
Good luck

Use regex to get value from varying strings

I am trying to figure out how to setup a regex to find a specific part of a string off of varying pieces of data.
IE, I have a PC log with the filename of TTEST7-17.txt or a filename of TTEST7-17.28-11-2018.txt
Basically, I just want the value "TTEST7-17" which would be the PC name.
But it has to pull that value no matter if the filename is TTEST7-17.txt or TTEST7-17.28-11-2018.txt
Each PC name and date is different, so it can't just match to one PC name and pull the string that way. It has to somehow determine IF it is formatted like TTEST7-17 or TTEST7-17.28.11.2018.txt and THEN either get rid of .txt or .28.11.2018.txt, no matter what the PC name is.
You can use the split() method. For example:
"TTEST7-17.28.11.2018.txt".Split('.')[0]
"TTEST7-17.txt".Split('.')[0]
Both of these give output of TTEST7-17.
Of course, if the name is in a variable, you can still use this method:
$fileName = "TTEST7-17.28.11.2018.txt"
$fileName.Split('.')[0]

What does this PowerShell code do?

I found the following code in a book about PowerShell scripts:
$Text = Read-Host -Prompt 'Input your text'
function FastTrain($text) {
$h = #{}
ForEach ($word in [regex]::split($text.ToLower(), '\W+'))
{
$h[$word] = ''
}
$h
}
FastTrain($Text)
I tried to run it, and got this:
What does it do? I think that it gets a string from the user, and then searches for characters, but I am not entirely sure.
Read a line of text from the user
$Text = Read-Host -Prompt 'Input your text'
Define a function
function FastTrain($text) {
Create a new hashtable. This is a data structure that maps keys to values.
$h = #{}
Lower-case the text argument and split it on successive non-word characters. This results in an array of “words” (however, since “word” characters for regular expressions are a quite arbitrary concept of little use anywhere, this will also include numbers, underscores, and a bunch of other things apart from letters).
ForEach ($word in [regex]::split($text.ToLower(), '\W+'))
{
Use the word as key in the hashtable and set the value to an empty string. This is merely a poor-man's version of a set, so the hashtable will contain all unique words from the input as keys (the values are irrelevant).
$h[$word] = ''
}
Return the hashtable
$h
}
Run above function on the input read earlier. This will also cause the hashtable from earlier to be printed on the screen since any object that is returned from a statement or pipeline will be output by default.
FastTrain($Text)
Note that this usage of PowerShell functions is technically incorrect and can easily lead to mistakes. A PowerShell function is invoked like any other PowerShell command, but not like a .NET method. So arguments are separated by spaces and there are no parentheses. In this case it works because there is only a single argument.
Given how atrocious this example is, I guess you should find a better book. This code looks nothing like how PowerShell code should look (in my opinion at least). The function performed by that code is essentially “Given a string, return all unique words from it”. A more PowerShell-ey version of that function would probably be:
function Get-UniqueWords($Text) {
$Text.ToLower() -split '\W+' | Select -Unique
}
No messing around with a hashtable, just to get a set of sorts. No unnecessary call to a .NET method where a PowerShell operator suffices. And using the pipeline to transform and/or filter a stream of data. Loops like that are often unnecessary since the pipeline is often easier to read and grasp (since you can just read how things are piped into another, instead of having to parse what happens to data structures to find out what happens to your data).
However, considering my gripe about \w/\W from earlier, the following regex would probably yield saner results for humans:
function Get-UniqueWords($Text) {
$Text.ToLower() -split '\P{L}+' | Select -Unique
}
This really only considers letters.
It is reading a sentence from the user:
$Text = Read-Host -Prompt 'Input your text'
It then creates an empty hashtable (a collection of key-value pairs):
$h = #{}
Then, splits the sentence into words:
[regex]::split($text.ToLower(), '\W+'))
And adds each one to the hashtable (with the word as the key, and nothing for the value):
$h[$word] = ''
Finally, it prints the hashtable:
$h
There is a function definition/call mixed in, but the above is what the code does.

How to grab a portion of an LDAP string into a variable (Powershell)

I am able to get the full LDAP path into a variable $strPath and it will return a result such as:
LDAP://CN=computername,OU=City,OU=Servers,OU=###,DC=dom,DC=ain,DC=com
or in other locations it could look like:
LDAP://CN=computername,OU=Servers,OU=##,DC=dom,DC=ain,DC=com
I want to return only the ##, ### or #### value (it can be either two, three or four characters) which is our district code.
So some computer objects have a city name in their LDAP string while others do not (depending on the size of the district), and the district code can be two, three or four characters long.
I'm guessing I want to do something like find text "Servers,OU=" and remove everything including and before that and also remove text ",DC=dom,DC=ain,DC=com" to get my final variable.
Thanks in advance!
You may be interested in the ADName module I wrote:
https://github.com/Bill-Stewart/PowerShell-ADName
For your first example, the OU code is the 4th element from the right:
LDAP://CN=computername,OU=City,OU=Servers,OU=###,DC=dom,DC=ain,DC=com
So for example, you can write this:
(Get-ADName "LDAP://CN=computername,OU=City,OU=Servers,OU=###,DC=dom,DC=ain,DC=com" -Split -ValuesOnly)[-4]
The -Split parameter splits the LDAP path into an array, and -ValuesOnly omits the CN=, OU=, DC=, etc. The [-4] means "return the 4th element from the end of the array."
How about something like this:
$ldapString = "LDAP://CN=computername,OU=Servers,OU=##,DC=dom,DC=ain,DC=com"
$temp = $ldapString.Split(",=")
$districtCode = $temp[[array]::IndexOf($temp,"DC") - 1]
It works with both and no extra imports. As long as you do not have a district code that is "DC".