我正在尝试编写正则表达式来标识if语句。我遇到的唯一问题是如果语句在括号中有括号,则会捕获它。例如:
if (condition_function(params)) {
statements;
}
我的表达式捕获除了这些之外的所有if语句:
if\s*\(([^\(\)]|\s)*\)\s*{(.|\s)*?}
有谁知道怎么写?
答案 0 :(得分:13)
使用正则表达式是不可能的,因为正则表达式只能匹配常规语言,而您尝试解析的语言是无上下文的,不是常规语言(感谢dirkgently和dmckee)。
看看你感兴趣的WP: Formal language theory ......
顺便说一下。如果表达式正确([[][]]
正确但[]][
不正确),您甚至无法检查仅由括号组成的表达式,这是您上面给出的“子问题”。
答案 1 :(得分:6)
我认为这可行。如果有人看到我没有看到的东西,就像它不起作用的原因,请回复。
if\s*\(((?:[^\(\)]|\((?1)\))*+)\)\s*{((?:[^{}]|{(?2)})*+)}
现在应该遇到的唯一问题是if语句中是否有if语句。
我已经在每一个我能想到的有效if语句上对此进行了测试,这可能会破坏它,并且唯一不起作用的是包含带有不匹配括号的字符串的语句。
更新:我发现上述正则表达式出错。它不会捕获if语句或语句部分中包含具有不匹配括号的字符串的语句。如下例所示:
if (var1 == "("){
echo "{";
}
然而,这是一个有效的if语句。解决方案:
if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?1)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?2)})*+)}\s*
这个正则表达式捕获所有if语句,甚至是包含具有不匹配括号的字符串的语句。
更新:我现在拥有它,以便捕获else和if if附加到if语句的语句。唯一的问题是它返回的捕获组是最后一个,如果在if语句中则是最后一个。希望我也能弄清楚如何解决这个问题。
if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?1)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?2)})*+)}\s*(?:(?:else\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?3)})*+)}\s*)|(?:else\s*if\s*\(((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^\(\)]|\((?4)\))*+)\)\s*{((?:(?:(?:"(?:(?:\\")|[^"])*")|(?:'(?:(?:\\')|[^'])*'))|[^{}]|{(?5)})*+)}\s*))*;
如果你想测试一下,这里有一个很棒的网站: http://gskinner.com/RegExr/
答案 2 :(得分:5)
您是否正在尝试编写正则表达式来解析非常规语言?那永远不会飞。
答案 3 :(得分:3)
您需要使用图灵完整语言编写代码。有些工具可以自动为您构建代码,例如Flex。但是,如果您只是遇到一个简单的问题,那么自己编写一些简单的解析代码可能最简单。下面是一些可以帮助您入门的示例C#代码。
public void TestIf()
{
var s = @"if (condition_function(params)) {
statements;
}";
var ifRegex = @"if *\(.*\) *{.*}";
if (Regex.IsMatch(s, ifRegex, RegexOptions.Singleline))
{
var firstParens = s.IndexOf('(');
if (firstParens != -1)
{
var conditionPart = s.Skip(firstParens + 1);
int stack = 1;
int lastParens = -1;
while(stack > 0)
{
for (int i = 0; i < conditionPart.Count(); i++)
{
var c = conditionPart.ElementAt(i);
if (c == '(')
{
stack++;
}
if (c == ')')
{
stack--;
}
if (stack == 0)
{
lastParens = i;
break;
}
}
}
if (lastParens != -1)
{
var condition = conditionPart.Take(lastParens);
Console.WriteLine(new string(condition.ToArray()));
}
}
}
}
答案 4 :(得分:1)
r = /\bif\s*\(/
txt = <<TXT
if(test)
if (test)
if (xyz)
; if
print x if(true)
TXT
p txt.scan(r)
if(something)..某些东西可以是任何东西..如果有一个带有括号结尾的字符串,并且你想要正确处理匹配的括号对,那么你很快就会得到一个很大的正则表达式。
你想用什么语言来对抗?
答案 5 :(得分:0)
如果你必须使用正则表达式,即使它永远不会捕获所有个案,那么这个更好:
if\s*\(((?!\s*\{).+)\)\s*\{(.|\s)*?\}
它使用positive lookahead((?!\s*\{).
)确保在结束)
之前捕获所有内容(除非您的条件语句中包含“{
”!正是regexp无法帮助你的地方)
答案 6 :(得分:0)
快速拍摄......
if\s*?\(.*?)\s*?(({?\s*?(.*?;)+\s*?})|(.*?;))
答案 7 :(得分:-1)
修改正则表达式(Koukaakiva),找不带括号 - https://regex101.com/r/fE6hA5/1 并为模式添加名称