test - regex perl online
Regex negativa para coincidencia de patrón de cuerda Perl (5)
¿Qué pasa con el uso de dos expresiones regulares (o tres)? Esto hace que tus intenciones sean más claras e incluso pueden mejorar tu rendimiento:
if ($string =~ /^(Clinton|Reagan)/i && $string !~ /Bush/i) { ... }
if (($string =~ /^Clinton/i || $string =~ /^Reagan/i)
&& $string !~ /Bush/i) {
print "$string/n"
}
Tengo esta expresión regular:
if($string =~ m/^(Clinton|[^Bush]|Reagan)/i)
{print "$string/n"};
Quiero unirme a Clinton y Reagan, pero no a Bush.
No funciona.
Si mi comprensión es correcta, entonces quiere hacer coincidir cualquier línea que tenga Clinton y Reagan, en cualquier orden, pero no con Bush. Según lo sugerido por Stuck, aquí hay una versión con aserciones anticipadas:
#!/usr/bin/perl
use strict;
use warnings;
my $regex = qr/
(?=.*clinton)
(?!.*bush)
.*reagan
/ix;
while (<DATA>) {
chomp;
next unless (/$regex/);
print $_, "/n";
}
__DATA__
shouldn''t match - reagan came first, then clinton, finally bush
first match - first two: reagan and clinton
second match - first two reverse: clinton and reagan
shouldn''t match - last two: clinton and bush
shouldn''t match - reverse: bush and clinton
shouldn''t match - and then came obama, along comes mary
shouldn''t match - to clinton with perl
Resultados
first match - first two: reagan and clinton
second match - first two reverse: clinton and reagan
según lo deseado, coincide con cualquier línea que tenga a Reagan y Clinton en cualquier orden.
Puede intentar leer cómo funcionan las aserciones anticipadas con ejemplos en http://www252.pair.com/comdog/mastering_perl/Chapters/02.advanced_regular_expressions.html
son muy sabrosos :)
Su expresión regular dice lo siguiente:
/^ - if the line starts with
( - start a capture group
Clinton| - "Clinton"
| - or
[^Bush] - Any single character except "B", "u", "s" or "h"
| - or
Reagan) - "Reagan". End capture group.
/i - Make matches case-insensitive
Entonces, en otras palabras, tu parte media de la expresión regular te está jodiendo. Como es un tipo de grupo "catch-all", permitirá cualquier línea que no comience con ninguna de las letras mayúsculas o minúsculas en "Bush". Por ejemplo, estas líneas coincidirían con su expresión regular:
Our president, George Bush
In the news today, pigs can fly
012-3123 33
O haces una anticipación negativa, como se sugirió anteriormente, o simplemente haces dos expresiones regulares:
if( ($string =~ m/^(Clinton|Reagan)/i) and
($string !~ m/^Bush/i) ) {
print "$string/n";
}
Como ha señalado mirod en los comentarios, el segundo control es bastante innecesario cuando se usa el cursor ( ^
) para hacer coincidir solo el comienzo de las líneas, ya que las líneas que comienzan con "Clinton" o "Reagan" nunca podrían comenzar con "Bush".
Sin embargo, sería válido sin los caretas.
Su expresión regular no funciona porque [] define una clase de caracteres, pero lo que quiere es una búsqueda anticipada:
(?=) - Positive look ahead assertion foo(?=bar) matches foo when followed by bar
(?!) - Negative look ahead assertion foo(?!bar) matches foo when not followed by bar
(?<=) - Positive look behind assertion (?<=foo)bar matches bar when preceded by foo
(?<!) - Negative look behind assertion (?<!foo)bar matches bar when NOT preceded by foo
(?>) - Once-only subpatterns (?>/d+)bar Performance enhancing when bar not present
(?(x)) - Conditional subpatterns
(?(3)foo|fu)bar - Matches foo if 3rd subpattern has matched, fu if not
(?#) - Comment (?# Pattern does x y or z)
Así que intente: (?! Bush)
Texto de ejemplo:
Clinton dijo
Bush usó lápices de colores
Reagan olvidó
Solo omitiendo un partido de Bush:
$ perl -ne ''print if /^(Clinton|Reagan)/'' textfile
Clinton said
Reagan forgot
O si realmente desea especificar:
$ perl -ne ''print if /^(?!Bush)(Clinton|Reagan)/'' textfile
Clinton said
Reagan forgot