考虑下面的脚本(它是伪语言的完全废话):
if (Request.hostMatch("asfasfasf.com") && someString.existsIn(new String[] {"brr", "hrr"})) {
if (Requqest.clientIp("10.0.x.x")) {
somevar = "1";
}
somevar = "2";
}
else {
somevar = "first";
}
string foo = "foo";
// etc. etc.
你如何从中获取if-block的参数和内容? if-block的格式为:
if<whitespace>(<parameters>)<whitespace>{<contents>}<anything>
我尝试使用String.split()
的正则表达式^if\s*\(|\)\s*\{|\}\s*
,但这种情况很糟糕。也就是说,问题是在内部if-block中也发现) {
,并且在许多地方也发现了结束}
。我不认为懒惰或急切的扩张在这里起作用。
那么......为了用regex实现这个,我需要指点什么呢?
我还需要在没有if-block代码的情况下获取剩余的字符串(所以代码从else { ...
开始)。仅使用String.split()
似乎很难,因为没有关于被解析的部分长度的信息。
我最初为此创建了一个基于循环的解决方案(大量使用String.substring()
),但它很无聊。我希望有更好的东西。我应该使用正则表达式还是创建一个自定义的泛型函数(除此之外还有很多其他情况)采用可解析的字符串和模式(考虑上面的if<whitespace>(...
模式)?
编辑:更改了返回变量赋值,否则就没有意义了。
答案 0 :(得分:2)
使用(或编写)解析器要比使用Regex执行此操作要好得多。
正则表达式非常适合某些人,但对于像这样的复杂解析,它很糟糕。另一个很糟糕的例子就是解析HTML - 你可以在有限的程度上完成它,但对于任何复杂的东西,DOM解析器都是一个更好的解决方案。
对于[非常]简单的解析器,你需要的是一个递归函数,它会搜索大括号{
和}
,每次遇到一个开括号时递归一个级别,然后返回找到一个右括号时备份一个级别。然后它需要在每个级别的两个大括号之间存储字符串内容。
答案 1 :(得分:1)
常规语言不起作用,因为regular grammar无法匹配诸如“任意数量的左括号后跟任意数量的近括号”之类的内容。为此需要context-free grammar。
除非您使用context-free grammar parser for Java或makes regular expressions no longer regular的正则表达式扩展名,否则基于循环的解决方案可能是最有效的解决方案。
答案 2 :(得分:1)
根据以上所述,您需要一个解析器。一种易于实现(并且编写有趣!)的类型是recursive descent parser with backtracking。还有很多解析器生成器,尽管其中大多数都有学习曲线。一个对Java友好的解析器生成器是JavaCC。