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

Posted

技术标签:

【中文标题】使用 Java 正则表达式模式解析字符串?【英文标题】:Parse string using Java Regex Pattern? 【发布时间】:2017-12-23 20:13:18 【问题描述】:

我有以下格式的 java 字符串。

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

使用 java.util.regex 包问题和模式类,我必须得到以下格式的输出字符串:

Output: [NYK:1100][CLT:2300][KTY:3540]

你能推荐一个可以帮助我获得上述输出格式的 RegEx 模式吗?

【问题讨论】:

你已经尝试过了吗? 【参考方案1】:

您可以使用这个正则表达式\[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]
regex demo \[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("]");

【讨论】:

和我做的差不多。我唯一的补充(这在某种程度上是一个偏好问题)是可以命名捕获组,例如name:(?&lt;name&gt;[A-Z]+),然后以matcher.group("name") 访问。只需在接入点明确说明您要访问的网段。 这是@tradeJmark 使用name:(?&lt;name&gt;[A-Z]+) 的好方法,然后以matcher.group("name") 访问 老实说这是我第一次看到它,我已经对其进行了测试,并且效果很好String regex = "\\[name:(?&lt;name&gt;[A-Z]+)\\]\\[distance:(?&lt;distance&gt;\\d+)\\]"; 我如果您不介意,将添加到我的答案中:) 当然,如果你喜欢,一定添加它。【参考方案2】:

如果字符串的格式是固定的,并且你总是只有 3 个 [...] 组在里面处理,你可以定义一个匹配 [name:...] 的块并将 2 部分捕获到单独的组并使用带有.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 demo 和regex demo。

块模式匹配:

\\s* - 0+ 个空格 \\[name: - 文字 [name: 子字符串 ([A-Z]+) - 第 n 组捕获 1 个或多个大写 ASCII 字符(也可以使用 \\w+]\\[distance: - 文字 ][distance: 子字符串 (\\d+) - 组 m 捕获 1 个或多个数字 ] - ] 符号。

.*%1$s%1$s%1$s.* 模式中,组将有 1 到 6 个 ID(通过替换模式中的 $1 - $6 反向引用引用),并且前导和最后 .* 将删除开头和结尾字符串(如果字符串可以包含换行符,则在模式开头添加(?s))。

【讨论】:

以上是关于使用 Java 正则表达式模式解析字符串?的主要内容,如果未能解决你的问题,请参考以下文章

java正则表达式,要求字符串只能包含数字、英文大小写、以及“-”符号

在Python中使用正则表达式解析具有重复模式的字符串?

Java中的String类下的正则表达式运用附带编程题解析

JavaScript正则表达式

使用 Python 正则表达式解析 Java Arrays.deepToString 输出的浮点字符串

正则表达式之实例