2013-08-31 1 views
0

J'ai ce journal:Perl Expression pour negate un groupe

The Foo bar, and Bar foo needs to Foo 
The Bar of Bar foo Bar Foo Foo 
Bar bar The Bar of Foo other Foo Bar 

Et je veux créer un expresion perl qui ne sélectionner que des mots qui ne sont pas Foo, ni bar. Le journal de résultat doit être:

The bar, and foo needs to 
The of foo 
The of other 

Je celui-ci:

^(Foo|Bar) 

Mais cela ne fonctionne pas.

Répondre

3

Si je comprends bien les commentaires, ce que vous voulez est de capturer tous les mots qui ne sont pas Foo ou Bar, puis probablement les imprimer en quelque sorte. Ce serait une façon de faire une telle chose:

/(?<!\S)(?!Foo|Bar)\S+(?!\S)/g 

Il est moins compliqué qu'il n'y paraît, voici la version annotée:

/ 
    (?<!\S)   # match cannot be preceded by non-whitespace 
    (?!Foo|Bar)(\S+) # capture non-whitespace that is not Foo|Bar 
    (?!\S)    # match cannot be followed by non-whitespace 
/gx     # match globally and ignore whitespace in regex 

Notez que /x est juste là, je peux utiliser les commentaires et nouvelles lignes à l'intérieur de l'expression régulière.

Les pièces de début et de fin de cette regex sont nos ancres de délimitation. Nous les utilisons pour nous assurer que nous n'obtenons pas de correspondances partielles. Ce sont des assertions de coup d'œil négatives, et des remplacements pour l'assertion de limite de mots \b un peu plus simple. Cependant, il n'était pas possible d'utiliser ici \b, car vous avez un caractère virgule dans votre chaîne. La raison pour laquelle nous utilisons (?!\S) au lieu de \s est que, bien qu'ils correspondent tous deux aux espaces, ce dernier ne correspond pas au début/à la fin de la chaîne. Puisque nous nous sommes assurés que nous ne pouvons pas obtenir de correspondances partielles, nous pouvons maintenant utiliser une simple alternance dans nos ancres avec une autre assertion de lookahead négative. C'est à dire. (?!Foo|Bar). Si cela ne correspond pas, nous capturons la chaîne avec (\S+).

est ici le cas de test j'ai créé pour ce problème:

perl -nlwe 'push @a, [/(?<!\S)(?!Foo|Bar)(\S+)(?!\S)/g] }{ print "@$_" for @a' 
The Foo bar, and Bar foo needs to Foo 
The Bar of Bar foo Bar Foo Foo 
Bar bar The Bar of Foo other Foo Bar 
^Z 
The bar, and foo needs to 
The of foo 
bar The of other 

Il utilise notre regex pour capturer des chaînes de $_ (l'entrée) et les pousser sur le tableau @a dans les références du tableau. Une fois l'entrée terminée (après l'opérateur esquimau }{), nous imprimons les références de tableau interpolées pour ajouter des espaces. "@$_" est équivalent à join " ", @$_ dans ce cas.

+2

+1 Je crois maintenant que c'est ce qu'il demandait – ChicagoRedSox

+0

@ChicagoRedSox Vous étiez celui qui a réussi à l'amener à le dire, donc +1 à vous pour cela. – TLP

3

Si vous essayez de supprimer les valeurs de la chaîne, une substitution travaillerait:

my $str = <<EOS; 
    The Foo bar, and Bar foo needs to Foo 
    The Bar of Bar foo Bar Foo Foo 
    Bar bar The Bar of Foo other Foo Bar 
EOS 
$str =~ s/(?:Foo|Bar) ?//g; 
print $str; 

>>>The bar, and foo needs to 
    The of foo 
    bar The of other 

Notez que le dernier « bar » (minuscule) est toujours là; Je suppose que c'était une erreur dans votre message.

+0

J'ai juste besoin de l'expression régulière avec la forme négative. quelque chose comme (Foo | Bar) mais avec la syntaxe de négation. Noot en utilisant! ~ – crsuarezf

+2

@ingcarlos - Alors s'il vous plaît réviser votre question pour expliquer ce que c'est que vous cherchez. Je pense que vous dites que vous voulez une regexp qui correspond à tous les mots de la chaîne qui ne sont pas Foo ou Bar (auquel cas ce n'est pas vraiment une question Perl, mais une question PCRE générale). – ChicagoRedSox

+0

Je sais que votre substitution fonctionnera comme un charme, mais j'ai aussi besoin d'une expression. – crsuarezf

Questions connexes