7

我有一个包含几行的文件,类似于:

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 解析器,因为该文件也包含其他类型的信息。

4

7 回答 7

6

我不太了解 Java 的正则表达式对象,但类似这种模式的东西可以做到:

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

假设 multiline 和 dotall 模式打开。

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

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

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

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

于 2008-12-26T21:13:16.847 回答
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"));
于 2008-12-25T20:55:46.600 回答
3

假设“内容”是一个包含文件内容的字符串,那么您的主要问题是您正在使用的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 模式。

于 2008-12-26T04:42:00.233 回答
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;

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

否则,我会支持 Properties 或 JYaml 建议。

于 2008-12-26T02:22:30.000 回答
0

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

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

于 2008-12-25T19:54:06.367 回答
0

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

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

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

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

如果没有 DOTALL,点将不会匹配换行符,因此您可以在正则表达式中明确指定它,从而允许您执行您所要求的操作。

于 2008-12-25T19:57:31.523 回答
0

你绝对应该检查YAML

你可以试试JYaml

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

ps 我已经尝试过YAML::XS中的示例文本,并且效果很好。

于 2008-12-26T00:21:59.603 回答