我正在尝试使用perl regex在模板模式上过滤Wikipedia转储:
{{tl|a|b|c}}
我想捕获a
和b
,其中a
,b
,c
等可以是任何一组UTF-8字符,不包括|
或}
。最终的}}
'之前可能会有未知数量的集合,但总会至少有两个(a
和b
)。所以你也可以得到:
{{tl|a|b}}
或{{tl|a|b|c|d}}
作为一名正则表达式新手,我首先想到尝试/\{\{tl\|(.+?)\|(.+?)\|?\}\}/
这给出了正确的完全匹配和第一次捕获,但在第二次捕获时失败,返回b|c|d
因为它找不到|}
。我需要告诉它在|
和}
之间寻找某些内容,但只有在找到|
时才会这样做。似乎应该有一个解决这个问题的简单方法,但我会陷入困境。
答案 0 :(得分:0)
你可以这样试试\{\{[^|}]*(?:\|[^|}]*)*\}\}
但不会得到捕获。
解释
\{\{ # Open {{
[^|}]* # Optional, not | or }
(?: # Group start
\| # |
[^|}]* # Optional not | or }
)* # Group end, optional 0 to many times
\}\} # Close }}
或者,使用\G
锚点并在第1组中获取结果
(?:\G(?!\A)|\{\{)([^|}]*)(?=(?:\|[^|}]*)*\}\})(?:\||\}\})
(?:
\G
(?! \A )
|
\{\{ # Open {{
)
( [^|}]* ) # (1), Data
(?= # Assert this is valid
(?:
\| # |
[^|}]* # Optional not | or }
)* # Group end, optional 0 to many times
\}\} # Close }}
) # End Assert
(?:
\| # Consume |
| # or
\}\} # Consume Close }}
)
答案 1 :(得分:0)
好的,我明白了。答案来自于使用(?:pattern)
进行“群集,而不是捕获”群组。 (来自perldoc)。使用此功能,您可以创建我们可以检查而无需捕获的组 - 在这种情况下,可以选择}}
或|c|d}}
。所以,作为一个正则表达式,答案是:
/\{\{tl\|([^\|]+?)\|(.+?)(?:\}\}|\|[^\}]+?\}\})/
第一部分与我之前的情况类似,/\{\{tl\|
标识模板的第一部分,([^\|]+?)\|
标识第一个捕获并停止|
。下一部分设置第二个捕获(.+?)
,它由\}\}
构造内部\|[^\}]+?\}\}
OR (?: )
的选择分隔。
希望这有助于其他人!