I want to use this regex in Powershell which uses gis flags,
https://regex101.com/r/yoM4cV/1
/(?<=#start)(. )(?=#end)/gis
to match sentence between #start and #end
#start
hello powershell regex
what is the equivalent of flags gis
#end
I cannot find any info about gis flags support for Powershell. Is this missing in Powershell ? If yes, what's the alternative ?
update : I ask because this returns false
$test=@'
#start
hello powershell regex
what is the equivalent of flags gis
#end
'@
$test -match (?<=#start)(. )(?=#end)
CodePudding user response:
Regexes in PowerShell are defined with string literals, not regex literals (structures like action/pattern/flags
).
The g
flag is not implemented as a regex option in PowerShell, you need to use mutliple matching. If you use Select-String
, you will need -AllMatches
option to match all occurrences. If you use the .NET regex API, ypu can use the Regex.Matches
method that finds all occurrences.
The i
and s
flag usage is simpler, you may just use them as inline modifier, (?s)
, (?i)
, or joined as (?si)
that you can place at the start of the pattern so that they could affect the whole pattern (or place them anywhere in the pattern so that to affect all the pattern to the right of them (and you can disable them with (?-s)
/(?-i)
/(?-si)
)).
If you define a regex object, you can use [Text.RegularExpressions.RegexOptions]'Singleline'
, [Text.RegularExpressions.RegexOptions]'IgnoreCase'
, or [Text.RegularExpressions.RegexOptions]'IgnoreCase, Singleline'
.
When you need to use s
flag, you must make sure your input is treated as a single multiline string. If you read files in, you need to make sure you use -Raw
option with Get-Content
.
Here is an example of the gis
flag "conversion" in PowerShell:
$rx = [System.Text.RegularExpressions.Regex]::new('(?<=#start)(.*?)(?=#end)', [Text.RegularExpressions.RegexOptions]'IgnoreCase, Singleline')
$test=@'
#start
hello powershell regex
what is the equivalent of flags gis
#end
'@
$rx.Matches($test).value
Output:
hello powershell regex
what is the equivalent of flags gis
The same result can be obtained with
($test | Select-String -Pattern '(?si)(?<=#start)(.*?)(?=#end)' -AllMatches).Matches.Value
CodePudding user response:
To fix your example, you need to write it like this:
$test -match '(?s)(?<=#start)(. )(?=#end)'
- Enable single-line mode
(?s)
to allow.
to match over multiple lines. - Quote the regular expression because
()
is the PowerShell grouping operator which in your example makes PowerShell try to interpret the regular expression pattern as PowerShell expressions, which does not work. Instead, pass it as literal string to-match
.
Detailed explanation:
From gis
, only i
(case-insensitive) and s
(single-line) are available as flags in PowerShell (or more generally in .NET, because PowerShell uses .NET RegEx support under the hood).
You can specify these either as inline flags at the beginning of the pattern ...
(?is)(?<=#start)(. )(?=#end)
... or by using the options
parameter of the Regex
class, which accepts a RegExOptions
argument:
$options = [System.Text.RegularExpressions.RegexOptions] 'IgnoreCase, Singleline'
[Regex]::Match('text', 'pattern', $options)
The g
(global) flag is not directly available. You can use it effectively by calling the [Regex]::Matches()
method, which finds all matches (contrary to [Regex]::Match()
and also the -match
operator which find only the first match). Its output is a collection of all matches that have been found.
Alternatively, you can use Select-String
with parameter -AllMatches
, as Wiktor Stribiżew's helpful answer demonstrates.
For demonstration purposes I've slightly modified your example so that it actually finds multiple matches (your original RegEx matches everything between first #start
to last #end
, so it only ever finds one match).
$text = @'
#start
hello powershell regex
what is the equivalent of flags gis
#end
#start
foobar
#end
'@
$pattern = '(?is)(?<=#start)(. ?)(?=#end)'
foreach( $match in [Regex]::Matches($text, $pattern) ) {
'----- Match -----'
$match.Groups[1].Value # Output the captured value of the 1st group
}
Output:
----- Match -----
hello powershell regex
what is the equivalent of flags gis
----- Match -----
foobar