使用Java正则表达式模式解析字符串?

9

我有一个Java字符串,格式如下。

String s = "City: [name:NYK][distance:1100] [name:CLT][distance:2300] [name:KTY][distance:3540] Price:"

使用java.util.regex包的matcher和pattern类,我必须以以下格式获取输出字符串:
Output: [NYK:1100][CLT:2300][KTY:3540]

你能提供一个正则表达式模式,帮助我得到上述的输出格式吗?

5
你已经尝试过了吗? - Kuba
2个回答

18

你可以像这样使用正则表达式\[name:([A-Z]+)\]\[distance:(\d+)\]

String regex = "\\[name:([A-Z]+)\\]\\[distance:(\\d+)\\]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(s);

StringBuilder result = new StringBuilder();
while (matcher.find()) {                                                
    result.append("[");
    result.append(matcher.group(1));
    result.append(":");
    result.append(matcher.group(2));
    result.append("]");
}

System.out.println(result.toString());

输出

[NYK:1100][CLT:2300][KTY:3540]
  • 正则演示
  • \[name:([A-Z]+)\]\[distance:(\d+)\] 表示获取两个组:第一个是\[name:([A-Z]+)\]后面的大写字母,第二个是\[distance:(\d+)\]后面的数字。

另一种解决方案来自@tradeJmark ,您可以使用此正则表达式:

String regex = "\\[name:(?<name>[A-Z]+)\\]\\[distance:(?<distance>\\d+)\\]";

所以您可以通过组名而不是索引轻松地获得每个组的结果,就像这样:

while (matcher.find()) {                                                
    result.append("[");
    result.append(matcher.group("name"));
    //----------------------------^^
    result.append(":");
    result.append(matcher.group("distance"));
    //------------------------------^^
    result.append("]");
}

3
几乎完全按照我的想法做的。我的唯一补充(这在某种程度上是个人偏好)是,捕获组可以命名,例如 name:(?<name>[A-Z]+),然后作为 matcher.group("name") 访问。这样,在访问点清楚地知道你要访问的片段,更易理解。 - Tim M.
这是使用 name:(?<name>[A-Z]+) 的好方法 @tradeJmark,然后可以通过 matcher.group("name") 访问。老实说,这是我第一次看到它,我已经测试过它,它非常有效。String regex = "\\[name:(?<name>[A-Z]+)\\]\\[distance:(?<distance>\\d+)\\]"; 如果您不介意,我会将其添加到我的答案中 :) - Youcef LAIDANI
如果你喜欢的话,当然可以加上去。 - Tim M.

4

如果字符串的格式是固定的,而且你总是只有3个[...]组需要处理,那么你可以定义一个匹配[name:...]并将两个部分捕获到不同组的块,并使用一个非常简单的代码与.replaceAll

String s = "City: [name:NYK][distance:1100] [name:CLT][distance:2300] [name:KTY][distance:3540] Price:";
String matchingBlock = "\\s*\\[name:([A-Z]+)]\\[distance:(\\d+)]";
String res = s.replaceAll(String.format(".*%1$s%1$s%1$s.*", matchingBlock), 
    "[$1:$2][$3:$4][$5:$6]");
System.out.println(res); // [NYK:1100][CLT:2300][KTY:3540]

请查看Java演示正则表达式演示

块模式匹配:

  • \\s* - 0个或多个空格
  • \\[name: - 匹配字面值字符串 [name:
  • ([A-Z]+) - 匹配并捕获一个或多个大写 ASCII 字符(也可以使用 \\w+
  • ]\\[distance: - 匹配字面值字符串 ][distance:
  • (\\d+) - 匹配并捕获一个或多个数字
  • ] - 匹配 ] 符号。

在模式.*%1$s%1$s%1$s.*中,组将具有1到6个ID(使用替换模式的$1 - $6 反向引用来引用它们),而首尾的.*将删除字符串的开头和结尾(如果字符串可能包含换行符,请在模式开头添加(?s))。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接