Question
J'utilise des expressions régulières pour essayer de faire correspondre les blocs de section dans un fichier INI. J'utilise la recette donnée dans le livre expressions régulières livre de recettes , mais il n'a pas semblent travailler pour moi.
Voici le code que je utilise:
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();
}
Voici le contenu de mon fichier d'entrée:
[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
Le problème est que sectionBlock
finit par être égale à tout le contenu du fichier, plutôt que la première section.
(je ne sais pas si ce qui compte, mais je fais cela sur Windows et les séparateurs de ligne dans s2
sont égaux à « \ r \ n » (au moins, c'est ce que le débogueur IDEA les affiche sous forme). )
Qu'est-ce que je fais mal ici?
La solution
Essayer cette regex à la place:
(?ms)^\[[^]\r\n]+](?:(?!^\[[^]\r\n]+]).)*
ou la chaîne Java regex littérale:
"(?ms)^\\[[^]\r\n]+](?:(?!^\\[[^]\r\n]+]).)*"
A (courte) explication:
(?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
En clair, on lirait:
un match « [ » suivi par un ou plusieurs caractères sauf '[', '\ r' et '\ n', suivi d'un « ] » (appelons-ce match de X). Ensuite, pour chaque chaîne vide dans le texte, d'abord regarder vers l'avenir pour voir si vous ne voyez pas un match X, si vous ne le faites pas, puis correspond à tout caractère.
Autres conseils
Vous utilisez le *
quantificateur gourmand correspondant à la plus longue chaîne possible. Utilisez le *?
quantificateurs réticents au lieu d'obtenir le plus correspondance possible.