我正在从模板生成配置文件。模板看起来像:
$Country$$Country$
WAN$Country$/$Country$
$Country$/29
$Country$/$Country$
"$fdfsrwdrdgf$1$asffdjhk"
这只是一个样本。我认为两个$
之间的任何东西都是占位符。因此,在上面的示例中,Country
是我唯一需要的占位符。我在Java代码中使用下面的正则表达式:
{"\\$[^$]*\\$";}
现在,我遇到的问题是,我不希望在上面的RE中使用引号内的任何内容,或者我想要更改RE以使其忽略引号内的内容(""
)。有人可以帮我吗?
答案 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$]