Pergunta

Estou usando expressões regulares para tentar corresponder a blocos de seção em um arquivo ini. Estou usando a receita dada no livro Livro de receitas de expressões regulares, mas não parece estar funcionando para mim.

Aqui está o código que estou usando:

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();
}

Aqui estão o conteúdo do meu arquivo de entrada:

[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

O problema é que sectionBlock acaba sendo igual ao conteúdo inteiro do arquivo, e não apenas à primeira seção.

(Não sei se isso importa, mas estou fazendo isso no Windows e nos separadores de linha em s2 são iguais a " r n" (pelo menos, é isso que a ideia depurador os exibe como).)

O que eu estou fazendo errado aqui?

Foi útil?

Solução

Experimente este regex em vez disso:

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

ou o java string literal regex:

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

Uma explicação (curta):

(?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

Em inglês simples, seria lido como:

Combine um '[' seguido por um ou mais caracteres, exceto '[', ' r' e ' n', seguido por um ']' (vamos chamar essa correspondência x). Então, para cada string vazia no texto, primeiro olhe para a frente para ver se você não vê uma correspondência X, se não o fizer, combine qualquer caractere.

Outras dicas

Você usa o quantificador ganancioso * Combinando a string mais longa possível. Use o quantificador relutante *? Em vez disso, obter a correspondência mais curta possível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top