复杂命名匹配组RegEx review
从这个示例字符串 $logLine = '{header[3]}_Pragmatic Praxis Initialization Log' 而且效果很好。但我在正则表达式方面太不熟练了,这是迄今为止我从无到有拼凑出的最复杂的正则表达式,我想知道是否有人在这种方法中看到了我没有看到的gotcha 或者我需要打开一些葡萄酒,庆祝达到某种RegEx理解里程碑 编辑: 所以我的成功让我过于自信。我决定让Tab成为必需的,但添加了一个可选的目标,可以是“控制台”或“文件”。所以我做了这个复杂命名匹配组RegEx review,regex,powershell,Regex,Powershell,从这个示例字符串 $logLine = '{header[3]}_Pragmatic Praxis Initialization Log' 而且效果很好。但我在正则表达式方面太不熟练了,这是迄今为止我从无到有拼凑出的最复杂的正则表达式,我想知道是否有人在这种方法中看到了我没有看到的gotcha 或者我需要打开一些葡萄酒,庆祝达到某种RegEx理解里程碑 编辑: 所以我的成功让我过于自信。我决定让Tab成为必需的,但添加了一个可选的目标,可以是“控制台”或“文件”。所以我做了这个 $logLine
$logLine = '{header[3]}_Pragmatic Praxis Initialization Log'
if ($logLine -match '^\{(?<type>[a-z]+)(?:-(?<target>(console|file)))\[(?<tab>\d*)\]\}_(?<string>.+)$') {
Write-Host "$($matches['type'])"
Write-Host "$($matches['target'])"
Write-Host "$($matches['tab'])"
Write-Host "$($matches['string'])"
}
在我看来,你好像误解了
(?:…)
的作用。该构造不定义可选匹配,而是定义非捕获组。(子)表达式(?:-(?console | file))
将要求字符串包含-console
或-file
,并将console
或file
作为命名匹配“目标”返回。要使组成为可选组,您需要在组后添加另一个?
^\{(?<type>[a-z]+)(?:-(?<target>console|file))?\[(?<tab>\d*)\]\}_(?<string>.+)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
^\{(?[a-z]+)(?:-(?控制台|文件))?\[(?\d*)\]\}
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
请注意,尾随表达式+
或*
使得将表达式锚定在字符串末尾($
)毫无意义,因此只需从表达式末尾删除$
您也不需要
console | file
周围的嵌套(未命名)捕获组。指定的捕获组已足够。如果数字变为2位,则匹配将失败。展示。更新正则表达式以避免该问题。@Gurman。说得好。这可能是值得改变的,尽管我怀疑它永远不会超过5。如果我需要捕获2个数字,那么可能需要验证实际值。\d+
将强制正则表达式至少匹配一个数字。但是你说它是可选的,因此我将它改为\d*
,而不是现在看到的\d+
@gurman,我开始想,既然我控制了这个tab值,也许我应该将它设为非可选的,在没有tab的地方使用[0],这样我就可以让regEx尽可能简单。匹配多个数字可能有意义,或者我可能会让它一直寻找一个数字,并在日志字符串格式不正确时抛出错误。
if ($logLine -match '^\{(?<type>[a-z]+)(-(?<target>(console|file)))?(\[(?<tab>\d+)\])?\}_(?<string>.+)') {
Write-Host "$($matches['type'])"
Write-Host "$($matches['target'])"
Write-Host "$($matches['tab'])"
Write-Host "$($matches['string'])"
}
^\{(?<type>[a-z]+)(?:-(?<target>console|file))?\[(?<tab>\d*)\]\}_(?<string>.+)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^