Соответствие Блокам раздела INI
Вопрос
Я использую регулярные выражения, чтобы попытаться сопоставить блоки разделов в INI-файле.Я использую рецепт, приведенный в книге Кулинарная книга по Регулярным Выражениям, но, похоже, у меня это не работает.
Вот код, который я использую:
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();
}
Вот содержимое моего входного файла:
[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
Проблема в том, что sectionBlock
в конечном итоге он равен всему содержимому файла, а не только первому разделу.
(Я не знаю, имеет ли это значение, но я делаю это в Windows и разделителях строк в s2
равны "
" (по крайней мере, именно так их отображает отладчик IDEA).)
Что я здесь делаю не так?
Решение
Попробуйте вместо этого это регулярное выражение:
(?ms)^\[[^]\r\n]+](?:(?!^\[[^]\r\n]+]).)*
или регулярное выражение строкового литерала Java:
"(?ms)^\\[[^]\r\n]+](?:(?!^\\[[^]\r\n]+]).)*"
(Краткое) объяснение:
(?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
На простом английском языке это звучало бы как:
Сопоставьте '[', за которым следует один или несколько символов, кроме '[', ' ' и '\ n', за которыми следует ']' (давайте назовем это совпадением X).Затем для каждой пустой строки в тексте сначала посмотрите вперед, чтобы увидеть, если вы не видите совпадения X, если нет, затем сопоставьте любой символ.
Другие советы
Вы используете жадный квантификатор *
соответствие максимально длинной строке.Используйте квантификатор сопротивления *?
вместо этого, чтобы получить кратчайшее возможное совпадение.