正则表达式在Java中提取标签值对

时间:2008-12-25 19:44:36

标签: java regex pattern-matching

我有一个包含几行类似于:

的文件
Name: Peter
Address: St. Serrano número 12, España
Country: Spain

我需要使用正则表达式提取地址,考虑到它可以包含点,特殊字符(ñ,ç),áéíó... ...

目前的代码有效,但看起来很丑:。

Pattern p = Pattern.compile("^(.+?)Address: ([a-zA-Z0-9ñÑçÇáéíóú., ]+)(.+?)$",
                            Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = p.matcher(content);
if (m.matches()) { ... }

编辑:地址字段也可以分为多行

Name: Peter
Address: St. Serrano número 12,   
Madrid
España
Country: Spain

编辑:我不能使用Properties对象或YAML解析器,因为该文件也包含其他类型的信息。

7 个答案:

答案 0 :(得分:6)

我不太了解Java的正则表达式对象,但是像这种模式的东西会这样做:

^Address:\s*((?:(?!^\w+:).)+)$

假设打开了多行和dotall模式。

这将匹配以地址开头的任何行,后跟任何内容,直到换行符和单个单词后跟冒号。

如果你知道下一个字段必须是“国家”,你可以稍微简化一下:

^Address:\s*((?:(?!^Country:).)+)$

诀窍在于重复组中的先行断言。 '(?!国家:)。'将匹配除字符串'Country:'的开头之外的所有内容,因此我们只将其粘贴在非捕获括号中(?:...)并用+量化它,然后将所有这些组合在正常捕获括号中。

答案 1 :(得分:3)

您可能希望查看Properties类而不是正则表达式。它为您提供了管理纯文本或XML文件以表示键值对的方法。

因此,您可以在示例文件中读取,然后在加载到Properties对象后获取这样的值:

Properties properties = new Properties();
properties.load(/* InputStream of your file */);

Assert.assertEquals("Peter", properties.getProperty("Name"));
Assert.assertEquals("St. Serrano número 12, España", properties.getProperty("Address"));
Assert.assertEquals("Spain", properties.getProperty("Country"));

答案 2 :(得分:3)

假设“content”是包含文件内容的字符串,那么您的主要问题是您使用的matches()应该使用find()

Pattern p = Pattern.compile("^Address:\\s*(.*)$", Pattern.MULTILINE);
Matcher m = p.matcher(content);
if ( m.find() )
{
  ...
}

关于MULTLINE和DOTALL模式的其他答案似乎有些混乱。 MULTILINE使^$锚点分别匹配逻辑行的开头和结尾。 DOTALL让点(句点,句号,等等)匹配行分隔符,如\n(换行)和\r(回车)。此正则表达式必须使用MULTILINE模式,不得使用DOTALL模式。

答案 3 :(得分:1)

我不是故意成为泥巴,但你必须使用正则表达式吗?为什么不让你未来的自己(或其他人)头疼并做到:

String line = reader.readLine();
while(line != null)
{
    line = line.trim();
    if(line.startsWith("Address: "))
    {
        return line.substr("Address: ".length()).trim();
    }
    line = reader.readLine();
}
return null;

当然,这也可以参数化并放入方法中。

否则,我会推荐属性或JYaml建议。

答案 4 :(得分:0)

不是Java人员,但"Address: (.*)$"不会工作吗?

编辑:没有Pattern.MULTILINE | Pattern.DOTALL选项应仅匹配该行。

答案 5 :(得分:0)

它可以包含换行符吗?如果它不能包含换行符,则不需要使用多行修饰符,而是可以使用

Pattern p = Pattern.compile("^Address: (.*)$");

如果可以的话,我能想到的另一种选择是

Pattern p = Pattern.compile("Address: (.*)\nCountry", Pattern.MULTILINE);

如果没有DOTALL,点将与换行符不匹配,因此您可以在正则表达式中明确指定它,从而可以执行您所询问的内容。

答案 6 :(得分:0)

您一定要查看YAML

您可以尝试JYaml

最重要的是它有多种语言的实现。

ps我在YAML::XS尝试过示例文本,效果很好。