Mon fichier d'entrée est comme ci-dessous:
$array[0] = "{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}" $array[1] = "{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}" $array[2] = "{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}" .. .. $array[5] = "{ ABC|*|XYZ:abc:pqr {GHI 0 68 0} {{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}} }"
7 Réponses :
Vous êtes beaucoup mieux à l'aide d'une machine à états que d'une regex pour ce type d'analyse. P>
Je ne pense pas que les expressions régulières pures sont ce que vous voulez utiliser ici (IMHO Cela pourrait même pas être analogue à l'aide de RegEx). P>
Au lieu de cela, construisez un petit analyseur, similaire à ce qui est montré ici: http: //www.perlmonks .org /? nœud_id = 308039 (Voir la réponse de Shotgunefx (Parson) le 18 novembre 2003 à 18:29 UTC) P>
Les expressions régulières sont réellement mauvaises pour assortir les accolades. En fonction de la profondeur que vous voulez aller, vous pouvez écrire une grammaire complète (qui est beaucoup plus facile que cela ne semble!) Pour Parse :: Recdescent . Ou, si vous voulez simplement obtenir les blocs, recherchez pour ouvrir des marques «{» et la fermeture '}', et gardez simplement le nombre de comptés du nombre de personnes ouvertes à tout moment. P>
Merci Zig, votre réponse est très utile.
Utilisez Texte :: équilibré p>
Merci ysth, c'est la meilleure solution !!
@Srilesh: Si vous aimez la réponse à cette réponse, veuillez cliquer sur la coche décrite à gauche de la réponse.
Ceci peut certainement être fait avec regex au moins dans les versions modernes de Perl: La regex correspond à un bloc d'attelle bouclé contenant soit des caractères sans bouclée, soit une récursivité en elle-même ( Correspond à des bretelles imbriquées) p> Edit: Le code ci-dessus fonctionne dans Perl 5.10+, pour les versions antérieures, la récursivité est un peu plus verbeuse: p> my $re; $re = qr/ \{ (?: [^{}]* | (??{$re}) )* \} /x;
my @array = $str =~ /$re/xg;
Essayé cela, mais je reçois la séquence d'erreur (? 0 ...) non reconnue dans Regex; marqué par <- ici dans m / (\ {(?: [^ {}] * | (? 0 <- ici)) * \}) /
@SRILESH => Le code i Publié précédemment Perl 5.10+, j'ai modifié ma réponse pour inclure une version qui fonctionnera dans les personnes âgées.
Solutions fournies par @ysth, @zaid, @leonbloy fonctionne bien pour moi, mais @ @ Eric's Solution a une très bonne performance. J'applique la récursive sur un fichier de 10 Mo et le résultat est vraiment rapide que les autres. Choisir votre réponse pour être la meilleure solution ici. Merci beaucoup.
Vous pouvez toujours compter les accolades:
my $depth = 0; my $out = ""; my @list=(); foreach my $fr (split(/([{}])/,$data)) { $out .= $fr; if($fr eq '{') { $depth ++; } elsif($fr eq '}') { $depth --; if($depth ==0) { $out =~ s/^.*?({.*}).*$/$1/s; # trim push @list, $out; $out = ""; } } } print join("\n==================\n",@list);
I Deuxième suggestion de Ysth d'utiliser le Texte :: équilibré code >
module. Quelques lignes vous mèneront sur votre chemin.
SORTIE H3>
{ABC|*|DEF {GHI 0 1 0} {{Points {}}}}
{ABC|*|DEF {GHI 0 2 0} {{Points {}}}}
{ABC|*|XYZ:abc:def {GHI 0 22 0} {{Points {{F1 1.1} {F2 1.2} {F3 1.3} {F4 1.4}}}}}
{ABC|*|XYZ:ghi:jkl {JKL 0 372 0} {{Points {}}}}
{ABC|*|XYZ:mno:pqr {GHI 0 34 0} {{Points {}}}}
{
ABC|*|XYZ:abc:pqr {GHI 0 68 0}
{{Points {{F1 11.11} {F2 12.10} {F3 14.11} {F4 16.23}}}}
}
Basé sur la suggestion de Ysth, j'ai utilisé du texte :: équilibré, mais je n'obtiens que le premier match. Merci de m'avoir aidé ici, j'ai besoin d'utiliser l'extrait_multiple sous aussi. Merci ..