Match INI Section Blocks

时光怂恿深爱的人放手 提交于 2019-12-12 05:48:41

问题


I'm using regular expressions to try to match section blocks in an INI file. I'm using the recipe given in the book Regular Expressions Cookbook, but it doesn't seem to be working for me.

Here is the code I'm using:

final BufferedReader in = new BufferedReader(
    new FileReader(file));
String s;
String s2 = "";
while((s = in.readLine())!= null)
    s2 += s + System.getProperty("line.separator");
in.close();

final String regex = "^\\[[^\\]\r\n]+](?:\r?\n(?:[^\r\n].*)?)*";
final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
String sectionBlock = null;
final Matcher regexMatcher = pattern.matcher(s2);
if (regexMatcher.find()) {
    sectionBlock = regexMatcher.group();
}

Here are the contents of my input file:

[Section 2]
Key 2.0=Value 2.0
Key 2.2=Value 2.2
Key 2.1=Value 2.1

[Section 1]
Key 1.1=Value 1.1
Key 1.0=Value 1.0
Key 1.2=Value 1.2

[Section 0]
Key 0.1=Value 0.1
Key 0.2=Value 0.2
Key 0.0=Value 0.0

The problem is that sectionBlock ends up being equal to the entire contents of the file, rather than just the first section.

(I don't know whether it matters, but I'm doing this on Windows and the line separators in s2 are equal to "\r\n" (at least, that's what the IDEA debugger displays them as).)

What am I doing wrong here?


回答1:


Try this regex instead:

(?ms)^\[[^]\r\n]+](?:(?!^\[[^]\r\n]+]).)*

or the Java String literal regex:

"(?ms)^\\[[^]\r\n]+](?:(?!^\\[[^]\r\n]+]).)*"

A (short) explanation:

(?ms)          // enable multi-line and dot-all matching
^              // the start of a line
\[             // match a '['
[^]\r\n]+      // match any character except '[', '\r' and '\n', one or more times
]              // match a ']'
(?:            // open non-capturing group 1
  (?!          //   start negative look-ahead
    ^          //     the start of a line
    \[         //     match a '['
    [^]\r\n]+  //     match any character except '[', '\r' and '\n', one or more times
    ]          //     match a ']'
  )            //   stop negative look-ahead
  .            //   any character (including line terminators)
)*             // close non-capturing group 1 and match it zero or more times

In plain English it would read as:

Match a '[' followed by one or more characters except '[', '\r' and '\n', followed by a ']' (let's call this match X). Then for every empty String in the text, first look ahead to see if you don't see a match X, if you don't, then match any character.




回答2:


You use the greedy quantifier * matching the longest possible string. Use the reluctant quantifier *? instead to get the shortest possible match.



来源:https://stackoverflow.com/questions/1561508/match-ini-section-blocks

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!