2

I'm trying to create a regex that works with the -match operator. The following already works:

# Exact match
$string1 = [Regex]::Escape('C:\Fruit\kiwi')
$regex = [regex] '^{0}$' -f $string1
'C:\Fruit\kiwi' -match $regex

# Match where trail is allowed ( -like 'c:\folder*')
$string1 = [Regex]::Escape('C:\Fruit\kiwi')
$regex = [regex] '^{0}' -f $string1
'C:\Fruit\kiwi\other folder' -match $regex

Now we're trying to have a match when there is something between two strings, but this fails:

# Match in between strings
$string1 = [Regex]::Escape("C:\Fruit")
$string2 = [Regex]::Escape("\kiwi")
$regex = [regex] '(?is)(?<=\b{0}\b)+?(?=\b{1}\b)' -f $string1, $string2
'C:\Fruit\d\kiwi' -match $regex

According to the docs it says:

  • '*' matches 0 or more times
  • '+' matches 1 or more times
  • '?' matches 1 or 0 times
  • '*?' matches 0 or more times, but as few as possible
  • '+?' matches 1 or more times, but as few as possible

So I was expecting that anything between C:\Fruit and \kiwi would result in true but this is not the case. What are we doing wrong? We're only after true false, because in the end we will glue these pieces together like regex1|regex2|...

DarkLite1
  • 13,637
  • 40
  • 117
  • 214
  • 1
    `.+?` matches 1 or more chars as few as possible. You quantified the lookbehind. You must quantify a consuming pattern instead, the `.`. – Wiktor Stribiżew Feb 27 '20 at 13:10
  • How to have it return `true` when there is something between the strings and `false` when there's nothing between them? – DarkLite1 Feb 27 '20 at 13:11
  • See https://regex101.com/r/9nxPPm/1. You just missed the `.`. BUT I suspect you will have issues due to `\b` word boundary as well. Try without them, `'(?is)(?<={0}).+?(?={1})'` – Wiktor Stribiżew Feb 27 '20 at 13:12
  • [Tried without word boundaries yet](https://regex101.com/r/9nxPPm/2) - `'(?is)(?<={0}).+?(?={1})'`? – Wiktor Stribiżew Feb 27 '20 at 13:17
  • This works `(?is)(?<=C:\\Fruit).+?(?=\\kiwi)` but the issue is I can't insert the escaped strings in here. The following fails: `(?is)(?<={0}).+?(?={1})` – DarkLite1 Feb 27 '20 at 13:20
  • Indeed, when fully typed out like in your proposal it is indeed working. However, not when the 2 strings are added to the regex string later. – DarkLite1 Feb 27 '20 at 13:25
  • So your problem is also how to build a pattern out of variables? – Wiktor Stribiżew Feb 27 '20 at 13:26
  • I guess so, as `$string1` and `$string2` are PowerShell variables. – DarkLite1 Feb 27 '20 at 13:27
  • 1
    `$regex = [regex] "(?is)(?<=$string1).+?(?=$string2)"`, then `'C:\Fruit\kiwi' -match $regex` yields *false* and `'C:\Fruit\d\kiwi' -match $regex` yields *true* – Wiktor Stribiżew Feb 27 '20 at 13:28
  • Perfect! That's it! Thank you very much. If you post it as an asnwer I'll mark it as solved. Weird that it can't be inserted with the `-f` operator. Anyhow, it's fixed, thank you :) – DarkLite1 Feb 27 '20 at 13:31
  • 1
    It can be inserted with the `-f` operator, you just need to provide parenthesis around the expression, that you are casting to `[regex]`: `$regex = [regex]('(?is)(?<={0}).+?(?={1})' -f $string1, $string2)` – Manuel Batsching Feb 27 '20 at 13:39

1 Answers1

1

You may fix your current code by using

$regex = [regex] "(?is)(?<=$string1).+?(?=$string2)"

Here,

  • .+? is used to match any 1+ chars as few as possible, you need to quantify a consuming pattern, not a lookbehind
  • Use double quotation marks to form the string literal in order to support string interpolation. Also, see more options at How to use a variable as part of a regular expression in PowerShell?
  • You should remove \b word boundaries as they are context dependent (you may add any further restrictions later if need be).
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563