如何为给定的情况编写正则表达式

时间:2016-03-29 11:27:15

标签: java regex

我正在从模板生成配置文件。模板看起来像:

$Country$$Country$
WAN$Country$/$Country$
$Country$/29
$Country$/$Country$
"$fdfsrwdrdgf$1$asffdjhk"

这只是一个样本。我认为两个$之间的任何东西都是占位符。因此,在上面的示例中,Country是我唯一需要的占位符。我在Java代码中使用下面的正则表达式:

{"\\$[^$]*\\$";}

现在,我遇到的问题是,我不希望在上面的RE中使用引号内的任何内容,或者我想要更改RE以使其忽略引号内的内容("")。有人可以帮我吗?

1 个答案:

答案 0 :(得分:3)

您可以使用Best Trick Ever

  

你还记得我们尝试匹配所有Tarzan实例的简单情况,除了那些用双引号括起来的吗?...好吧,你现在看到当你使用最好的正则表达式技巧时问题变得多么简单:

     

"Tarzan"|(Tarzan)

     

真的?那是吗?

     

是。诀窍是我们在交替的左侧匹配我们不想要的东西|),然后我们捕获我们想要的东西在右边侧即可。当我们的编程语言返回结果时,我们会忽略整体匹配(即垃圾桶),而是将我们的全部注意力转移到第1组匹配,其中包含我们所追求的内容。

所以,你需要的只是

"[^"]+"|(\$[^$]*\$)

或(如果你有转义序列:

"[^"\\]*(?:\\.[^\\"]*)*"|(\$[^$]*\$)

获取捕获组#1的内容。请参阅regex demo

Demo

String s = "$Country$$Country$\nWAN$Country$/$Country$\n$Country$/29\n$Country$/$Country$\n\"$fdfsrwdrdgf$1$asffdjhk\""; 
Pattern pattern = Pattern.compile("\"[^\"\\\\]*(?:\\\\.[^\\\\\"]*)*\"|(\\$[^$]*\\$)"); 
Matcher matcher = pattern.matcher(s);
List<String> res = new ArrayList<>();
while (matcher.find()){
    if (matcher.group(1) != null) {
        res.add(matcher.group(1)); 
        //                    ^  - Get Group 1 only! 
    }
} 
System.out.println(res);
// => [$Country$, $Country$, $Country$, $Country$, $Country$, $Country$, $Country$]