Use a PowerShell Substring to Search Inside a String

PowerShell

Need to search for a string inside a string? Never fear, PowerShell substring is here! In this article, I guide you through how to ditch objects and search inside strings.

The PowerShell substring

I love being on social media because I always come across something interesting related to PowerShell. Sometimes it is a trick I didn’t know about or a question someone is trying to figure out. I especially like the questions because it helps me improve my understanding of how people learn and use PowerShell. Workload permitting, I’m happy to jump in and help out.

One such recent challenge centered on string parsing. Although you’ll hear me go on and on about object in the pipeline, there’s nothing wrong with parsing strings if that’s what you need. There are plenty of log files out there that need parsing, and PowerShell can help.

Search for a string in a string

In this case, I’m assuming some sort of log file is in play. I don’t know what the entire log looks like or what the overall goal is. That’s OK. We can learn a lot from the immediate task. Let’s say you have a string that looks like this:

Mailbox:9WJKDFH-FS349-1DSDS-OIFODJFDO-7F21-FC1BF02EFE26 (O'Hicks, Jeffery(X.))

I’ve changed the values a little bit and modified my name to make it more challenging. The goal is to grab the name from the string. I want to end up with:

O'Hicks, Jeffery(X.)

There are several different ways you can accomplish this. The right way probably depends on your level of PowerShell experience and what else you might want to accomplish. I’ll start by assigning this string to variable $s.

Using the PowerShell split operator

When I am faced with string parsing, sometimes it helps to break the string down into more manageable components. To do that I can use the split operator. There is also a split method for the string class. I am going to assume you will take some time later to read more about PowerShell split.

$s -split "\s",2

The “\s” is a regular-expression pattern that means a space. The 2 parameter value indicates that I only want two substrings. In other words, split on the first space found.

Using the split operator in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the split operator in Windows PowerShell. (Image Credit: Jeff Hicks)

I end up with an array of two elements. All I need is the second one.

$t = ($s -split "\s",2)[1]

Using the substring method

Now for the parsing fun, let’s use the string object’s SubString() method.

$t.Substring(1,$t.length-2)

I am telling PowerShell to get part of the string in $t, starting at character position 1 and then getting the next X number of characters. In this case, X is equal to the length of the string, $t, minus 2. This has the net effect of stripping off the outer parentheses.

Using the PowerShell substring method
Using the PowerShell substring method (Image Credit: Jeff Hicks)

Here’s a variation, where I split on the “(” character.

($s -split "\(",2)
$t = ($s -split "\(",2)[1]
$t.Substring(0,$t.length-1)
Using the split operator on a character in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the split operator on a character in Windows PowerShell. (Image Credit: Jeff Hicks)

The difference that this gets rid of the leading parenthesis. So, all I need to do is get everything up to the last character. By the way, if you look at a string object with Get-Member, you will see some Trim methods. These are for removing leading and/or training white space. Those methods don’t apply here.

Split a string using array index numbers

There’s one more way to split a string that you might find useful. You can treat all strings as an array of characters. This means you can use array index numbers to reference specific array elements.

Counting elements in an array starts at 0. If you run $t[0] you’ll get the first element of the array, in this case ‘O’. You can also use the range operator.

$t[0..5]
An alternative to splitting a string in Windows PowerShell. (Image Credit: Jeff Hicks)
An alternative to splitting a string in Windows PowerShell. (Image Credit: Jeff Hicks)

Right now, $t has an extra ) at the end that I don’t want. I need to get everything up to the second-to-last element.

$t[0..($t.length-2)]

This will give me an array displayed vertically, which you can see in the screenshot above. With that said, it’s easy to join the spliced string back together.

-join $t[0..($t.length-2)]

It might look a bit funny to lead with an operator, but if you read about_join, then you’ll see this is a valid approach that works.

Using the -join operator to put our string back together. (Image Credit: Jeff Hicks)
Using the -join operator to put our string back together. (Image Credit: Jeff Hicks)

Simple function for string parsing

I’m assuming you want an easy way to do this type of parsing, so I wrote a simple function.

Function Optimize-String {
[cmdletbinding()]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="Enter a string of text")]
[ValidateNotNullorEmpty()]
[string]$Text,
[int]$Start=0,
[int]$End=0
)
#trim off spaces
$string = $Text.Trim()
#get length value when starting at 0
$l = $string.Length-1
#get array elements and join them back into a string
-join $string[$Start..($l-$end)]
} #end function

The function takes a string of text and returns the substring minus X number of characters from the start and X number of characters from the end. Now I have a easy command to parse strings.

Using the optimize-string function in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the optimize-string function in Windows PowerShell. (Image Credit: Jeff Hicks)

If you look through the code, then you’ll see I am using the Trim() method. I am using it because I don’t want any extra spaces at the beginning or end of the string to be included.

Going back to my original string variable, I can now parse it with a one-line command:

optimize-string ($s -split("\s",2))[1] -Start 1 -end 1
Using the optimize-string function to search inside a string
Using the optimize-string function to search inside a string (Image Credit: Jeff Hicks)

If it makes more sense to you to break this into separate steps, that’s OK.

$arr = $s -split("\s",2)
$text =  $arr[1]
optimize-string $text -Start 1 -end 1

Next time we’ll look at string parsing using regular expressions, and it won’t be scary, I promise.