用于字符串中可选等号分隔符的 Powershell 正则表达式
Powershell Regex for optional equal sign separator in string
在下面的测试字符串中,键之间可能有 一个等号 或 一个或多个 space 个字符和价值。如果存在等号,可以选择在 and/or 前面加上零个或多个 space 个字符。
$MyTstString = "KeyX = ValueY"
$RegExString = "^(?<Key>.+)(?<Sep>\s*=\s*)(?<Value>.*)$"
$MyTstString -match $RegExString | Foreach {$Matches}
哪个正则表达式适合我?
将 RegExString 更改为
$RegExString = "^(?<Key>.+)(?<Sep>\s*=\s*|\s+)(?<Value>.*)$"
当TestString为“KeyA = ValueB”时导致Key和Sep不正确
注意:\s
匹配所有形式的白色space,而不仅仅是spaces,包括制表符、换行符……要将匹配限制为仅 spaces,请逐字使用 space (
) 代替下面的 \s
。
我建议 使用 -split
操作结合 多重赋值 代替:
$key, $value = $MyTstString -split '\s*=\s*|\s+', 2
注:, 2
部分(指定可选的<Max-strings>
operand) ensures that only at most two tokens are returned; otherwise, the value part could end up itself get split up if it happens to contain whitespace or =
. Thanks, iRon.
如果您还想捕获分隔符字符串:
$key, $sep, $value = $MyTstString -split '(\s*=\s*|\s+)', 2
至于你试过的:
As Bender the Greatest points out, a -match
操作 标量 LHS:
- returns
$true
或 $false
指示正则表达式是否匹配。
- 如果确实匹配,则用它找到的 - 一个 - 匹配填充 automatic
$Matches
variable(它永远不会寻找更多)。
(相比之下,使用 array(集合)作为 LHS,-match
returns(可能为空)sub -匹配元素数组,并且不填充$Matches
。)
使用您原来的方法,使用更正和简化的正则表达式形式:
你的正则表达式的问题(两种变体)是(?<Key>.+)
太贪心了 并包括 =
之前的 space 或捕获组匹配中的最后一个 space。
最简单的解决方案是简单地使+
量词非贪婪:(?<Key>.+?)
;或者,将匹配的字符限制为 除白色 space 和 =
:
之外的所有字符
(?<Key>[^\s=]+)
.
$RegExString = '^(?<Key>.+?)(?<Sep>\s*=\s*|\s+)(?<Value>.*)$'
'KeyX1 = ValueY1', 'KeyX2 ValueY2', 'KeyX3=ValueY3' |
ForEach-Object {
if ($_ -match $RegExString) {
[pscustomobject] @{ Key = $Matches.Key; Sep = $Matches.Sep; Value = $Matches.Value}
}
}
以上结果:
Key Sep Value
--- --- -----
KeyX1 = ValueY1
KeyX2 ValueY2
KeyX3 = ValueY3
在下面的测试字符串中,键之间可能有 一个等号 或 一个或多个 space 个字符和价值。如果存在等号,可以选择在 and/or 前面加上零个或多个 space 个字符。
$MyTstString = "KeyX = ValueY"
$RegExString = "^(?<Key>.+)(?<Sep>\s*=\s*)(?<Value>.*)$"
$MyTstString -match $RegExString | Foreach {$Matches}
哪个正则表达式适合我?
将 RegExString 更改为
$RegExString = "^(?<Key>.+)(?<Sep>\s*=\s*|\s+)(?<Value>.*)$"
当TestString为“KeyA = ValueB”时导致Key和Sep不正确
注意:\s
匹配所有形式的白色space,而不仅仅是spaces,包括制表符、换行符……要将匹配限制为仅 spaces,请逐字使用 space (
) 代替下面的 \s
。
我建议 使用 -split
操作结合 多重赋值 代替:
$key, $value = $MyTstString -split '\s*=\s*|\s+', 2
注:, 2
部分(指定可选的<Max-strings>
operand) ensures that only at most two tokens are returned; otherwise, the value part could end up itself get split up if it happens to contain whitespace or =
. Thanks, iRon.
如果您还想捕获分隔符字符串:
$key, $sep, $value = $MyTstString -split '(\s*=\s*|\s+)', 2
至于你试过的:
As Bender the Greatest points out, a -match
操作 标量 LHS:
- returns
$true
或$false
指示正则表达式是否匹配。 - 如果确实匹配,则用它找到的 - 一个 - 匹配填充 automatic
$Matches
variable(它永远不会寻找更多)。
(相比之下,使用 array(集合)作为 LHS,-match
returns(可能为空)sub -匹配元素数组,并且不填充$Matches
。)
使用您原来的方法,使用更正和简化的正则表达式形式:
你的正则表达式的问题(两种变体)是
(?<Key>.+)
太贪心了 并包括=
之前的 space 或捕获组匹配中的最后一个 space。最简单的解决方案是简单地使
+
量词非贪婪:(?<Key>.+?)
;或者,将匹配的字符限制为 除白色 space 和=
:
之外的所有字符(?<Key>[^\s=]+)
.
$RegExString = '^(?<Key>.+?)(?<Sep>\s*=\s*|\s+)(?<Value>.*)$'
'KeyX1 = ValueY1', 'KeyX2 ValueY2', 'KeyX3=ValueY3' |
ForEach-Object {
if ($_ -match $RegExString) {
[pscustomobject] @{ Key = $Matches.Key; Sep = $Matches.Sep; Value = $Matches.Value}
}
}
以上结果:
Key Sep Value
--- --- -----
KeyX1 = ValueY1
KeyX2 ValueY2
KeyX3 = ValueY3