2011-05-10 12 views
17

¿Puede alguien explicarme por qué la salida de este pequeño script de Perl es "foofoo" (y no "foo")?Comportamiento extraño en una expresión regular de perl con sustitución global

#!/usr/bin/perl -w 
my $var="a"; 
$var=~s/.*/foo/g; 
print $var."\n"; 

Sin la opción g, funciona como pensé, pero ¿por qué es el patrón de coincidencia de opciones globales dos veces?

En salida Bash es "foo" como se esperaba

echo "a"|sed -e "s/.*/foo/g" 

Cualquier explicación sería apreciada.

Respuesta

12

Primero .* coincide con la a, luego coincide con la cadena vacía después de la a. ¿Tal vez quieres .+?

+1

Sí, eso es, estoy convencido de '$ var = ~ s /^.*/ foo/g;' No me di cuenta de que coincidiría con la cadena vacía, pero en realidad es algo obvio – rcout

+1

Pensándolo bien, * es se supone que es codicioso, ¿cómo es? – rcout

+2

@rcout: la codicia tiene que ver con los tiempos de una repetición, de alguna manera no avanzará más allá del final de la cadena – ysth

6

Esto se debe a que está utilizando en lugar de .*.+

El modificador * le dice al motor de expresiones regulares para que coincida (y vuelva a colocar en su ejemplo) la cadena "a", a continuación, una cadena de longitud cero (y reemplazar también).

Puede probar esto mediante el uso de esta expresión regular en su código de ejemplo:

$var=~s/(.*)/<$1>/g; 

A continuación, verá esta salida:

"<a><>" 
6

Si agrega re a su código:

use re 'debug'; 

verá que la expresión regular coincide con éxito dos veces:

Compiling REx `.*' 
size 3 Got 28 bytes for offset annotations. 
first at 2 
    1: STAR(3) 
    2: REG_ANY(0) 
    3: END(0) 
anchored(MBOL) implicit minlen 0 
Offsets: [3] 
     2[1] 1[1] 3[0] 
Matching REx ".*" against "a" 
    Setting an EVAL scope, savestack=5 
    0 <> <a>    | 1: STAR 
          REG_ANY can match 1 times out of 2147483647... 
    Setting an EVAL scope, savestack=5 
    1 <a> <>    | 3: END 
Match successful! 
Matching REx ".*" against "" 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 1: STAR 
          REG_ANY can match 0 times out of 2147483647... 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 3: END 
Match successful! 
Matching REx ".*" against "" 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 1: STAR 
          REG_ANY can match 0 times out of 2147483647... 
    Setting an EVAL scope, savestack=7 
    1 <a> <>    | 3: END 
Match possible, but length=0 is smaller than requested=1, failing! 
          failed... 
Match failed 
foofoo 
Freeing REx: `".*"' 
8

es más divertido si se intenta

$var=~s/.*?/foo/g; 

Usted recibirá

foofoofoo 

El? el modificador coincide con 1 o 0 veces. Si se quita la g, obtendrá

fooa

, ya que sólo sustituirá a la cadena vacía, el primero que encuentre. Me encanta Perl.

Cuestiones relacionadas