Regex 正则表达式匹配
我想写一个正则表达式来匹配Regex 正则表达式匹配,regex,Regex,我想写一个正则表达式来匹配 () (()) (()()) ((())) ()()() 等等。正则表达式无法有效处理这种嵌套结构。您需要的是语法和语法分析器。你的语法很简单。如果您使用的是python,请尝试pyparsing或funcparserlib 使用pyparsing,您可以执行以下操作: from pyparsing import nestedExpr nestedExpr().parseString( "(some (string you) (want) (to) test)" )
()
(())
(()())
((()))
()()()
等等。正则表达式无法有效处理这种嵌套结构。您需要的是语法和语法分析器。你的语法很简单。如果您使用的是python,请尝试pyparsing或funcparserlib 使用pyparsing,您可以执行以下操作:
from pyparsing import nestedExpr
nestedExpr().parseString( "(some (string you) (want) (to) test)" ).asList()
这将返回一个包含嵌套字符串的已解析组件的列表。nestedExpr的默认分隔符是括号,因此不需要做任何额外的操作。如果要使用funcpasrerlib,可以尝试以下方法
from funcparserlib.parser import forward_decl, many, a
bracketed = forward_decl()
bracketed.define(a('(') + many(bracketed) + a(')'))
之后你可以打电话
bracketed.parse( "( (some) ((test) (string) (you) (want)) (to test))" )
它将返回元组中已解析的元素。如果您使用的语言的正则表达式语法不支持递归匹配,我将为您提供我的简单Javascript实现,您应该能够使用自己选择的语言来实现:
function testBraces(s) {
for (var i=0, j=0; i<s.length && j>=0; i++)
switch(s.charAt(i)) {
case '(': { j++ ; break; }
case ')': { j-- ; break; }
}
return j == 0;
}
函数测试括号{
对于(变量i=0,j=0;i=0;i++)
开关(s.charAt(i)){
大小写“(”:{j++;break;}
case'):{j--;break;}
}
返回j==0;
}
在这里你可以玩它:所有这些声称你不能使用模式来匹配带有平衡嵌套参数的字符串的答案都是错误的。假装现代编程语言所匹配的模式仅限于教科书意义上的“常规语言”是不切实际的。只要你允许反向引用,它们就不存在了。这使得现实世界中的模式比教科书中的版本更加匹配,从而使它们更加实用 匹配平衡参数的最简单模式是
\((?:[^()]*+|(?0))*\)
。但是你不应该写,因为它太紧凑了,不容易阅读。您应该始终使用/x
模式编写它,以允许空白和注释。这样写吧:
m{
\( # literal open paren
(?: # begin alternation group
[^()]*+ # match nonparens possessively
| # or else
(?0) # recursively match entire pattern
)* # repeat alternation group
\) # literal close paren
}x
对于命名抽象,以及将抽象的定义和顺序与其执行分离,还有很多要说的。这就导致了这类事情:
my $nested_paren_rx = qr{
(?&nested_parens)
(?(DEFINE)
(?<open> \( )
(?<close> \) )
(?<nonparens> [^()] )
(?<nested_parens>
(?&open)
(?:
(?&nonparens) *+
|
(?&nested_parens)
) *
(?&close)
)
)
}x;
my$nested\u paren\u rx=qr{
(?&嵌套参数)
(?(定义)
(? \( )
(? \) )
(? [^()] )
(?
(?&打开)
(?:
(?&非当事人)*+
|
(?&嵌套参数)
) *
(?&关闭)
)
)
}x;
第二种形式现在可以包含在更大的模式中
不要让任何人告诉你不能使用模式来匹配递归定义的东西。正如我刚才所展示的,你当然可以
当你这样做的时候,确保永远不要写线噪声模式。你不必,也不应该。任何禁止空白、注释、子例程或字母数字标识符的编程语言都是不可维护的。所以,在你的模式中使用所有这些东西
当然,为这类工作选择合适的语言确实有帮助。☺ 祝你好运。你需要一个有堆栈的有限状态自动机来解析这样的东西。它不能只用正则表达式解析,因为它不够强大。什么是。。。1.你的意见是什么(举例),2。你想拿什么来。什么正则表达式不起作用?请澄清——介于什么之间?你想在那一串括号中的什么地方找到呢?我有一个条件,如果它匹配()或(())或(())或()()或(()),它将保持为真。括号可以是任何数字。如果条件不匹配,我想进入false部分。输入可以是上面提到的任何示例,一些错误的输入只会是(()或(())etcno)(不是有效字符串为什么(())无效?它匹配“介于()之间的任何内容”(在本例中,“任何内容”都是()是的,
j
不应该低于零,因为它表示不平衡。我只是注意到for循环的结束条件中的&&j>=0
位(它一直在那里还是在五分钟的窗口中编辑了它?)。完美。@Tim:它从一开始就在那里,就像在演示中一样(在jsFiddle上)这个答案也是错误的:现代编程语言中的模式完全可以胜任这项工作。我不知道一些正则表达式风格会进行递归模式匹配,因为在我使用的语言中,它们不会。大多数情况下(阅读:关于我的雇主项目)我不能选择我使用的语言。但我已经修正了我的答案。@tchrist:如果您指定了示例将使用的语言,那就好了。当然,如果OP指定了他希望用什么语言来实现这一点,那也会好。@avi:同意;因此我的最后一行。据我所知,递归模式在Per中工作l、 PHP和PCRE。我使用的变量语法是用于Perl的,但这在某种程度上是个偶然的问题。我预计,在PCRE支持递归模式的情况下,未来几年将有更多的语言采用递归模式。不过,请小心,因为PCRE比Perl对头对尾递归有更多的限制。@tchrist,您的语句“backreferences”使正则表达式变得不规则是不正确的。Back references只是许多替代方法的简写-()\1
只是aa | bb | cc | dd |…
您可以对所有使用Back references的方法进行相同的转换。的确[…]< /代码>符号和<>代码> 符号都是经典正则表达式中的替代品的速写。另一方面,递归正则表达式是一个非常不同的鱼儿,使用该特征阻止它是规则的…@ toByoDave:考虑模式<代码>(+).*\1
。这需要超出自动机状态所需的辅助存储,而且确实需要与匹配的输入字符串长度成比例的存储。这显然违反了ʀ的一个基本属性ᴇɢᴜʟᴀʀlangua