Subscribe via Email

Subscribe via RSS/JSON


Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan


PowerShell regexp match with lines above and below

Wasn’t aware of this until today when I needed to do this. The Select-String cmdlet in PowerShell can select strings based on a regexp (similar to findstr in regular command prompt) with the added benefit that it can also return context. Which is to say you can return the line that matches your pattern and also lines above or below it. Pretty cool!

In my case I needed to scan the output of portqry.exe and also get the UUIDs of the lines that match. These UUIDs are shown on the line above so I did something like this:

The -Context 1,0 switch is the key here. The first number tells the cmdlet how many lines before to show, the second number how many lines after.

Using PowerShell to insert a space between characters (alt method using regular expressions and -replace)

A reader (thanks Jeff!) of my previous post wrote to mention that there’s an even easier way to insert a space between characters. Use the -replace operator thus:

So simple! 

The -replace help page doesn’t give much details on using regular expressions. Jeff pointed to the Regex.Replace() method help page, which is where he got the idea from. I tried to search for more info on this and came across this post by Don Jones and this Wiki page on TechNet. 

I had wanted to use the -replace operator initially but was stumped at how to get automatic variables like $1, $2, $3, … for each of the (bracketed) matches it finds. Turns out there’s no need to do that! Each match is a $1.

ps. From Jeff’s code I also realized I was over-matching in my regular expression. The thumbprints are hex characters so I only need to match [0-9A-F] rather than [0-9A-Z]. For reference here’s the final code to get certificate thumbprints and display with a space:

Using PowerShell to insert a space between characters (or: Using PowerShell to show certificate fingerprints in a friendly format)

I should be doing something else, but I got looking at the installed certificates in my system. That’s partly prompted by a desire to make a list of certificates installed on my Windows 8.1 machines, and read up on how the various  browsers use these certificates (my understanding is that Firefox and Chrome have their own stores in addition (or in exclusion?) to the default Windows certificate store). 

Anyways, I did the following to get a list of all the trusted CA in my certificate store:

I quickly got side tracked from that when I noticed the thumbprint and wondered what I could do to space it out. What I meant is: if you go to your browser and check the thumbprint/ fingerprint, it is usually a bunch of 40 characters but with spaces between every two characters. Like this: D5 65 8E .... In contrast the PowerShell output gave everything together. The two are same, but I needed and excuse to try something, so wondered how I could present it differently. 

Initially I thought of using the -replace operator but then I thought it might be better to -split and -join them. Both will make use of regular expressions I think, and that’s my ultimate goal here – to think a bit on what regular expressions I can use and remind myself on the caveats of these operators. 

The -split operator can take a regular expression as the delimiter. Whenever the expression matches, the matched characters are considered to identify the end of the sub-string, and so the part before it is returned. In my case I want to split along every two characters, so I could do something like this:

This, however, will return no output because every block of two characters is considered as the delimiter and split off, but there then remains nothing else to output. So the result is a bunch of empty lines. 

To make the delimiter show in the output I can enclose it within brackets:

Now the output will be an empty line followed a block of two characters (the delimiter), followed by an empty line, and so on …

I can’t -join these together with a delimiter because then the empty lines too get pulled in. Here’s an example -join using the + character as delimiter so you can see what happens:

What’s happening is that the empty objects too get sandwiched between the output we want.

Now, if only there was a way to cull out the empty objects. Why of course, that’s what the Where-Object cmdlet can do! 

Like this perhaps (I only let through non-empty objects):

Or perhaps (I only let through objects with non-zero length):

Or perhaps (I only let through non-empty objects; the \S matches anything that’s not whitespace):

Using any one of these I can now properly -join

And finally what I set out to get in the first place:

Update: While writing this post I discovered one more method. Only let through objects that exist (so obvious, why didn’t I think of that!):

Also check out this wiki entry for the Split() method to the String object. Doesn’t work with regular expressions, but is otherwise useful. Especially since it can remove empty entries by default. 

Update2: See this follow-up post for a typo in my regexp above as well as an alternate (simpler!) way of doing the above.

Modifying Junk Email configuration using PowerShell

You can use the (Set|Get)-MailboxJunkEmailConfiguration cmdlets to set or view the Junk Email configuration of a mailbox. For instance:

From the Get-MailboxJunkEmailConfiguration output above I can see Junk Email configuration is Enabled for this mailbox, all email addresses in the Contacts folder of this mailbox are automatically added to the trusted senders list, any emails from the domain are considered trusted senders and delivered to the mailbox, and no domain is considered blocked and hence not delivered to mailbox. Further, the mailbox is not solely relying on these trusted lists – if it were, then only addresses in the trusted list would be allowed through and everything else discarded.

To change these values use the Set-MailboxJunkEmailConfiguration cmdlet. Its syntax is pretty straightforward.

To add entries to the trusted or blocked senders lists one must retrieve the entries first and then append to it. So either do it the longish way like this:

Or do it all in one go like this:

In either case the result is the same:

Of course, goes without saying, the beauty of being able to do something like this via PowerShell rather than manually on Outlook or Outlook Web App is that you can do bulk action. Like for instance:

Easy to see at one shot what the status for each user is.

I can get rid of the OU name in the Identity column via some format-table regexpery.

A variation of the above:

Here I am using regexp to strip out the “” bit so I only get the user identity and the OU it is in. I do this by making the + regexp operator non greedy so it doesn’t match all the input text – rather, it stops at the first “/” character. I then put this regexp in brackets to club it together and tell PowerShell to match exactly two instances of this (hence the {2}) so what remains is the bit which I want. Regexps are great when they work and you can make sense of them!

Dot star replace matches twice

Have a look at this:

Works as expected. It matches “bc” in the input text and replaces the output with “ff” followed by whatever was matched (in this case “bc”).

The second example makes things clearer. It’s obvious in retrospect but easy to forget. We are not matching for the words “bc”, we are actually matching for a pattern “abc”: the text “bc” preceded by an “a”. If such a pattern is found, that matched pattern is replaced with the words “ff” followed by part of the matched pattern (in this case “bc”).

The third example simply drives home the point that the pattern can be anywhere in the input and that multiple instances are matched & replaced.

Another one:

What’s going wrong here? I expected the entire input to be replaced with one word – “blah”. Why do I have it twice then? This happens even if I do variations of the above thus:

It looks like the pattern matching-replacing is taking place twice. Lines 3 & 4 make it clearer above. The first time “abc” is replaced with “blah[abc]” as expected, and then a matching-replacing seems to occur again on that same input text adding “blah[]” to “blah[abc]”. No matching seems to take place however, or the matched pattern is empty, and that’s why there’s no text within the square brackets.

Hmm. So maybe that’s the problem! The matched pattern is empty – which is acceptable as my regexp pattern is .* and that matches empty text too. If I replace .* with .+ (at least one character must match) does that work as expected?

Sweet, it does!

Moral of the story: be careful using the .* pattern – apart from matching everything in the input, it will also match the emptiness that remains.

Extract a variable from a bunch of files

I have a couple of TXT files. They contain some text, along with a line like this:

The version number keeps changing.

I want to list all these files along with the value of $version in that file. Here’s how:

The result is something like this:

It’s pretty straight-forward what I am doing. I use Get-Item to get all the TXT files. Pipe it to a ForEach-Object loop. Within that I use the Get-Content cmdlet to get the contents of the file. I could have stored the contents in a variable and then done the remaining bits, instead I send it directly to the -match operator to get out lines that contain the pattern I am looking for. After this I replace the line to extract the numbers between double-quotes and store that in a variable. Finally I output the file name and the version (only if a version was found).

The two patterns pattern took me a while to figure out so I’ll delve a bit more into it here. I use a similar pattern for the -match and -replace operators so my comments here apply to both. The patterns are pretty straight-forward but for the fact that I need to match symbols such as dollar ($) and double-quotes (“). That in itself is not a hassle as I can escape them and match as $ or ” but that didn’t work in my case. I kept getting errors like this:

Why does this happen? Thanks to a Stack Overflow post I got the answer. What happens is that although I escape the $ as $ within the regular expression, since $ is a special character for PowerShell (variable names) it clubs the $ with the word “version” and treats it as a variable $version. And since this variable isn’t defined, it expands to an empty string which PowerShell passes to the -match operator as the pattern “^”. This pattern doesn’t make sense and so we get the error above.

Workaround is to double escape the $ symbol. As `$. If we do that I get the following error:

Not sure why I get an error here. The period character is an operator in PowerShell, and since the error points to that something roundabouts the period operator is confusing PowerShell. Ideally the whole pattern ^`$version = ".*" should be passed to the -match operator, but PowerShell only seems to be passing ^`$version = and using the period as a deference operator to that string. Which of course will not work because the left hand side is a string and not an object, but also because the right hand side *"$" is not a property name. So again it looks to be similar to the earlier error. The double quotes are being usurped by PowerShell first, before passing to the -match operator, and so they too need to be double escaped.

Hence I use the pattern ^`$version.* for the -match operator and the pattern ^`$version = `"(.+)`"$ for the -replace operator. Double-escaping the $ and ” characters.