我需要帮助来构建以下模式的正则表达式,我必须以特定模式收集字符串。
示例输入字符串:
*!
hostname ${hostname} !
!
!
ip name-server ${ip-name-server}
no ipv6 cef
!
!
voice class codec 1
codec preference 1 ${codec-pref-1} codec preference 2 ${codec-pref-2} codec preference 3 ${codec-pref-3} !
!
session target dns:${session-targ-DNS} dtmf-relay rtp-nte*
输出应该是 主机名, IP 名称服务器, 编解码器-pref-1, 编解码器-pref-2, 编解码器-pref-3, session 目标-DNS,
即应收集并检索格式为 ${string} 的字符串。
我尝试了如下代码
public void fetchKeyword(String inputString) {
String inputString1 = inputString.replace("\n", " ");
Pattern p = Pattern.compile("\\${$1} ");
Matcher m = p.matcher(inputString1);
int i=0;
while(m.find()){
System.out.println(m.group(i));
i++;
}
}
我还尝试了 .${.*}
、(.)${.*?}
等模式,但没有达到预期的结果。我遇到了如下异常
Exception in thread "main" java.util.regex.PatternSyntaxException: Illegal repetition near index 1
\${$1}
^
at java.util.regex.Pattern.error(Unknown Source)
at java.util.regex.Pattern.closure(Unknown Source)
at java.util.regex.Pattern.sequence(Unknown Source)
at java.util.regex.Pattern.expr(Unknown Source)
at java.util.regex.Pattern.compile(Unknown Source)
at java.util.regex.Pattern.<init>(Unknown Source)
at java.util.regex.Pattern.compile(Unknown Source)
at myUtil.ReplaceString.fetchKeyword(ReplaceString.java:70)
at myUtil.ReplaceString.main(ReplaceString.java:20)
有人可以帮忙吗?
最佳答案
您可以使用此解决方案来检索占位符文本:
// test string
String input = "! hostname ${hostname} ! ! ! ip name-server "
+ "${ip-name-server} no ipv6 cef ! ! "
+ "voice class codec 1 codec preference 1 ${codec-pref-1} "
+ "codec preference 2 ${codec-pref-2} codec preference 3 "
+ "${codec-pref-3} ! ! session target "
+ "dns:${session-targ-DNS} dtmf-relay rtp-nte";
// compiling pattern with one group representing the text inside ${}
Pattern p = Pattern.compile("\\$\\{(.+?)\\}");
// initializing matcher
Matcher m = p.matcher(input);
// iterating find
while (m.find()) {
// back-referencing group 1 each find
System.out.println(m.group(1));
}
输出
hostname
ip-name-server
codec-pref-1
codec-pref-2
codec-pref-3
session-targ-DNS
注释
$1
您使用的习惯用法用于替换(即String#replaceAll
),以反向引用索引组。- 索引组在您的模式中声明为
()
或者从 Java 7 开始,作为命名组:(?<name>X)
- 组的索引是由模式中分组惯用语的出现来定义的,而不是像您想象的那样通过匹配的迭代来定义
- 请参阅文档 here
- 我作为示例显示的模式是双重转义
$
,{
和}
字符 - 还值得注意的是,它使用不情愿的量词 (
+?
) 来尽可能匹配直到下一个已知字符:}
- 最后,如上所述,组 #1 在括号内定义,代表任何字符(直到结束
}
) - 只要
${something}
内没有出现换行符,输入文本中的换行符就不会对该模式的结果产生负面影响。习语 - 如果发生这种情况,您需要在解析之前清理换行 rune 本,或者使用
Pattern.DOTALL
参数化您的模式。然后清理匹配中的换行符(不过后者看起来不是一个很好的解决方案) - 如Thomas提到,此模式假定您的表达式在
{}
之间永远不会为空。如果您确实有一个空表达式,则解析从空表达式开头到下一个非空表达式结尾(如果适用)的所有内容都会失败。因此,要么保证您没有空表达式,要么您想使用.*?
而不是.+?
(另请参阅托马斯的回答)。
关于Java 正则表达式构建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39612225/