{"id":80305,"date":"2016-10-14T00:01:46","date_gmt":"2016-10-14T07:01:46","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/?p=80305"},"modified":"2019-02-18T09:10:25","modified_gmt":"2019-02-18T16:10:25","slug":"powershell-regex-crash-course-part-3-of-5","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/powershell-regex-crash-course-part-3-of-5\/","title":{"rendered":"PowerShell regex crash course \u2013 Part 3 of 5"},"content":{"rendered":"<p><strong>Summary<\/strong>: Thomas Rayner, Microsoft Cloud &amp; Datacenter Management MVP, shows the basics of working with regular expressions in PowerShell.<\/p>\n<p>Hello! I\u2019m Thomas Rayner, a proud Cloud &amp; Datacenter Management Microsoft MVP, filling in for The Scripting Guy! this week. You can find me on Twitter (<a target=\"_blank\" href=\"http:\/\/twitter.com\/MrThomasRayner\">@MrThomasRayner<\/a>), or posting on my blog, <a target=\"_blank\" href=\"http:\/\/workingsysadmin.com\">workingsysadmin.com<\/a>. This week, I\u2019m presenting a five-part crash course about how to use regular expressions in PowerShell. Regular expressions are sequences of characters that define a search pattern, mainly for use in pattern matching with strings. Regular expressions are extremely useful to extract information from text such as log files or documents. This isn\u2019t meant to be a comprehensive series but rather, just as the name says: a crash course. So, buckle up!<\/p>\n<p>Many people are intimidated by regular expressions, or \u201cregex\u201d. If you see something like <strong>\u2018(\\d{1,3}\\.){3}(\\d{1,3})\u2019<\/strong> and your eyes start glazing over, don\u2019t worry. By the end of this series, you\u2019ll have the skills to identify that pattern matches IP addresses. For the uninitiated, big strings of seemingly random characters appear indecipherable, but regex is an incredibly powerful tool that any PowerShell pro needs to have a grip on.<\/p>\n<p>Already, we have introduced a few different regex concepts. We started with some quantifiers and then moved on to explain special characters. Now, let&#8217;s talk about character classes. Enter the wonderful world of brackets!<\/p>\n<p>First, curly braces. That&#8217;s right: <strong>{<\/strong> and <strong>}<\/strong>. We use curly braces to signify the number of times that we want a specific pattern or character to occur in our matches. Let&#8217;s look at an example.<\/p>\n<p style=\"padding-left: 60px\"><code>something123' -match '\\d{3}'\u00a0 #returns true<\/code><\/p>\n<p>We know that the <strong>\\d<\/strong> part of this pattern matches any digit. The part in the curly braces is new. What we&#8217;re saying here is that we want the part that comes right before the curly braces to occur the number of times shown within the curly braces. So, we want any digit, and we want that to happen three times. If we change that number, we change what we&#8217;re looking to match.<\/p>\n<p style=\"padding-left: 60px\"><code>something123' -match '\\d{4}'\u00a0 #returns false<\/code><\/p>\n<p>This comes back false because we want four digits in a row, and that pattern doesn&#8217;t exist in &#8220;something123&#8221;. We can also specify ranges.<\/p>\n<p style=\"padding-left: 60px\"><code>something123' -match '\\d{2,4}'\u00a0 #returns true<\/code><\/p>\n<p>Here, we&#8217;re saying, &#8220;I want any digit between two and four times&#8221;. The first number is the minimum number of occurrences, and the second is the maximum. If there are two numbers separated by a comma, then that&#8217;s the range of occurrence frequency. You can also go <strong>{2,}<\/strong> to specify \u201ctwo or more times\u201d.<\/p>\n<p>Second, round () brackets. In regex, we can use round brackets to group things. Think of it like algebra; whatever is in the brackets will be evaluated and returned as a match together. Let&#8217;s put this together with what we learned about curly braces.<\/p>\n<p style=\"padding-left: 60px\"><code>'hello123hello123hello123' -match '(hello123){3}'\u00a0 #returns true<\/code><\/p>\n<p>I&#8217;m telling PowerShell to look for the pattern &#8220;hello123&#8221; three times. &#8220;hello123&#8221; is the pattern that\u2019s within the round brackets, and I want it three times. You can expand on this concept.<\/p>\n<p style=\"padding-left: 60px\"><code>'hello123hello123 something else' -match '(hello123){1,4}\\s?something'\u00a0 #returns true<\/code><\/p>\n<p>Maybe this isn&#8217;t the most practical example, but what I&#8217;m matching is &#8220;one to four occurrences of &#8216;hello123&#8217; followed by zero or one whitespace, followed by &#8216;something'&#8221;. Because that pattern is present, this line returns true. Now, we are ready to examine the example in one of the earlier paragraphs more closely.<\/p>\n<p style=\"padding-left: 60px\"><code>'192.168.1.1' -match '(\\d{1,3}\\.){3}\\d{1,3}'<\/code><\/p>\n<p>Let&#8217;s break it down.<\/p>\n<ul>\n<li><code>\\d{1,3}<\/code> &#8211; looking for one to three digits<\/li>\n<li><code>\\.<\/code> &#8211; looking for a period<\/li>\n<\/ul>\n<p>Therefore, <code>\\d{1,3}\\.<\/code>\u00a0is looking for one to three digits, followed by a period<\/p>\n<ul>\n<li><code>(\\d{1,3}\\.){3}<\/code> &#8211; looking for three occurrences of &#8220;one to three digits followed by a period&#8221;<\/li>\n<\/ul>\n<p>So, we have &#8220;three occurrences of &#8216;one to three digits followed by a period&#8217; and then one to three more digits&#8221;. Sounds like an IP address, right? This would match, also, something like 999.830.60.450, which is not a valid IP address. The example still works, though.<\/p>\n<p>What about square [] brackets? In regex, we use square brackets to denote a set. That might mean a range of characters or an array of characters that we&#8217;re interested in.<\/p>\n<p style=\"padding-left: 60px\"><code>'something' -match '[f-q]$' #returns true<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>'something' -match '[h-q]$'\u00a0 #returns false<\/code><\/p>\n<p>In the first example, we&#8217;re looking for the pattern &#8220;a letter between f and q, followed by the end of the line&#8221;. Because &#8220;something&#8221; ends in <em>g<\/em>, which is between <em>f<\/em> and <em>q<\/em>, the pattern is a match. In the second example, we&#8217;re looking for &#8220;a letter between h and q, followed by the end of the line&#8221; which doesn&#8217;t exist since g falls outside that range. This is case sensitive in regex, but the <strong>\u2013match<\/strong> operator doesn&#8217;t take case into account.<\/p>\n<p>You can negate a set, too, using the <strong>^<\/strong> symbol. That is to say, match &#8220;not this character&#8221;.<\/p>\n<p style=\"padding-left: 60px\"><code>'something' -match '[^q]$'\u00a0 #returns true<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>'something' -match '[^g]$'\u00a0 #returns false<\/code><\/p>\n<p>The first example says, &#8220;something that is not a q followed by the end of the line&#8221; which matches our string of &#8220;something&#8221;. The next example says, &#8220;something that is not a g followed by the end of the line&#8221; which returns false, because &#8220;something&#8221; ends in a <em>g<\/em> followed by the end of the line.<\/p>\n<p>If you like examples, stay tuned! Next Friday, I&#8217;m going to talk about lookaheads and lookbehinds, then the next day is ALL EXAMPLES!<\/p>\n<p>Wow, Thomas! \u00a0I never knew working with regular expressions could be this easy! I\u2019m going to have my calendar set to read up on next week\u2019s post!\u00a0 Can\u2019t wait!<\/p>\n<p>I invite you to follow the Scripting Guys on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to them at <a target=\"_blank\" href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow.<\/p>\n<p>Until then, always remember that, with Great PowerShell comes Great Responsibility.<\/p>\n<p><strong>Sean Kearney<\/strong>\nHonorary Scripting Guy\nCloud and Datacenter Management MVP<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Thomas Rayner, Microsoft Cloud &amp; Datacenter Management MVP, shows the basics of working with regular expressions in PowerShell. Hello! I\u2019m Thomas Rayner, a proud Cloud &amp; Datacenter Management Microsoft MVP, filling in for The Scripting Guy! this week. You can find me on Twitter (@MrThomasRayner), or posting on my blog, workingsysadmin.com. This week, I\u2019m [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[568,687],"tags":[56,652,45],"class_list":["post-80305","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hey-scripting-guy","category-regular-expressions","tag-guest-blogger","tag-thomas-rayner","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Thomas Rayner, Microsoft Cloud &amp; Datacenter Management MVP, shows the basics of working with regular expressions in PowerShell. Hello! I\u2019m Thomas Rayner, a proud Cloud &amp; Datacenter Management Microsoft MVP, filling in for The Scripting Guy! this week. You can find me on Twitter (@MrThomasRayner), or posting on my blog, workingsysadmin.com. This week, I\u2019m [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80305","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=80305"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80305\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=80305"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=80305"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=80305"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}