2009-10-13 7 views
0

J'utilise des expressions régulières pour essayer de faire correspondre des blocs de section dans un fichier INI. J'utilise la recette donnée dans le livre Regular Expressions Cookbook, mais ça ne semble pas fonctionner pour moi.Correspondance des blocs de section INI

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 à la totalité du contenu le fichier, plutôt que seulement la première section.

(Je ne sais pas si c'est important, mais je le fais sous 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)

Qu'est-ce que je fais mal ici?

+0

Je pense que le problème est Pattern.MULTILINE - becuase vous utilisez quantificateurs avides l'expression rationnelle tentera de correspondre autant que possible-à-dire le contenu du fichier – heferav

+0

Si je ne l'utilise pas Pattern.MULTILINE, je toujours obtenir le fichier entier. –

Répondre

5

Essayez cette regex à la place:

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

ou Java chaîne 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 :

Correspond à un '[' suivi d'un ou plusieurs caractères sauf '[', '\ r' et '\ n', suivi d'un ']' (appelons cela correspondance X). Ensuite, pour chaque chaîne vide dans le texte, regardez d'abord pour voir si vous ne voyez pas un match X, si vous n'avez pas, puis correspondre à n'importe quel caractère.

0

Vous utilisez le quantificateur gourmand * correspondant à la chaîne la plus longue possible. Utilisez plutôt le quantificateur réticent *? pour obtenir la correspondance la plus courte possible.

+0

Voulez-vous dire comme ceci?: "^ \\ [[^ \\] \ r \ n] +] (?: \ R? \ N (?: [^ \ R \ n]. *)?) *? " Lorsque j'utilise cela, cela me renvoie uniquement "[Section 2]", plutôt que le bloc Section 2 entier. –