开发者

Match INI Section Blocks

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;开发者_如何学Python
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?


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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜