Operador de predicción negativo

(?! ...) Operador de ``trailing'' o ``mirar-adelante'' negativo.

Por ejemplo /foo(?!bar)/ contiene a cualquier ocurrencia de foo que no vaya seguida de bar. Aparentemente el operador ``mirar-adelante'' negativo es parecido a usar el operador ``mirar-adelante'' positivo con la negación de una clase. Sin embargo existen al menos dos diferencias:

Otros dos ejemplos:

Nótese que el ``mirar-adelante'' negativo es diferente del ``mirar-atrás''. No puede usar este operador para ``mirar-atrás'': (?!foo)bar/ no casa con una aparición de bar que no ha sido precedida de foo. Lo que dice (?!foo) es que los tres caracteres que siguen no puede ser foo. Así, foo no pertenece a (?!foo)bar/, pero foobar pertenece a (?!foo)bar/ porque bar es una cadena cuyos tres siguientes caracteres son bar y no son foo.

> cat foobar.pl
#!/usr/bin/perl

 my $a = shift;

 if ($a =~ m{(?!foo)bar}i) { print "$a casa la primera. \$& = $&\n"; }
 else { print "$a no casa la primera\n"; }

 if ($a =~ m{(?!foo)...bar}i) { print "$a casa la segunda. \$& = $&\n"; }
 else { print "$a no casa la segunda\n"; }

> foobar.pl foo
foo no casa la primera
foo no casa la segunda
> foobar.pl foobar
foobar casa la primera. $& = bar
foobar no casa la segunda
Si quisieramos conseguir algo parecido tendríamos que escribir algo asi como /(?!foo)...bar/ que casa con una cadena de tres caracteres que no sea foo seguida de bar. En realidad, es mucho mas fácil escribir:
if (/bar/ and $` !~ /foo$/)

Veamos otro ejemplo:

   1 #!/usr/bin/perl -w
   2 $s = "foobar";
   3 if ($s =~ /(?!foo)bar/) {
   4   print "$s matches (?!foo)bar\n";
   5 }
   6 if ($s !~ /(?!foo)...bar/) {
   7   print "$s does not match (?!foo)...bar\n";
   8 }
   9 if ($s =~ /bar/ and $` !~ /foo$/) {
  10   print "$s matches /bar/ and \$` !~ /foo\$/\n";
  11 }
  12 else {
  13   print "$s does not match /bar/ and \$` !~ /foo\$/\n";
  14 }
Los resultados de la ejecución de este ejemplo son:
> lookbehind.pl
foobar matches (?!foo)bar
foobar does not match (?!foo)...bar
foobar does not match /bar/ and $` !~ /foo$/

Casiano Rodríguez León
Licencia de Creative Commons
Principios de Programación Imperativa, Funcional y Orientada a Objetos Una Introducción en Perl/Una Introducción a Perl
por Casiano Rodríguez León is licensed under a Creative Commons Reconocimiento 3.0 Unported License.

Permissions beyond the scope of this license may be available at http://campusvirtual.ull.es/ocw/course/view.php?id=43.
2012-06-19