¿Por qué '[az] *' coincide con cadenas no alfabéticas?

9

Tengo un archivo alphanumcon estas dos líneas:

123 abc
this is a line

Estoy confundido sobre por qué, cuando ejecuto sed 's/[a-z]*/SUB/' alphanum, obtengo el siguiente resultado:

SUB123 abc
SUB is a line

Yo estaba esperando:

123 SUB
SUB is a line

Encontré una solución (uso sed 's/[a-z][a-z]*/SUB/'en su lugar), pero no entiendo por qué funciona y el mío no.

¿Puede usted ayudar?

Fakher Mokadem
fuente
@Kamaraj, ese es similar, pero tiene los patrones de shell frente a la confusión de expresiones regulares en la parte superior (y las respuestas se concentran en el primero, ya que eso es lo ls foo*que usa allí). Pero de todos modos, si encuentra preguntas que son duplicadas, creo que también debería poder marcarlas como tales.
ilkkachu
echa un vistazo a regexr.com para visuales en vivo y explica
RozzA
@RozzA Tenga en cuenta que el sitio web al que se vincula admite expresiones regulares de Javascript y Perl, no expresiones regulares de POSIX.
Kusalananda

Respuestas:

28

El patrón [a-z]*coincide con cero o más caracteres en el rango ade z(los reales personajes son dependientes de la localización actual). Hay cero caracteres de este tipo al comienzo de la cadena 123 abc(es decir, el patrón coincide), y también cuatro de ellos al comienzo de this is a line.

Si necesita al menos una coincidencia, use [a-z][a-z]*o [a-z]\{1,\}, o habilite expresiones regulares extendidas con sed -Ey use [a-z]+.

Para visualizar dónde coincide el patrón, agregue paréntesis alrededor de cada coincidencia:

$ sed 's/[a-z]*/(&)/' file
()123 abc
(this) is a line

O, para ver todos los partidos en las líneas:

$ sed 's/[a-z]*/(&)/g' file
()1()2()3() (abc)
(this) (is) (a) (line)

Compare ese último resultado con

$ sed -E 's/[a-z]+/(&)/g' file
123 (abc)
(this) (is) (a) (line)
Kusalananda
fuente
77
Técnicamente [a-z]coincide con elementos de clasificación que pueden estar formados por más de un personaje. Por ejemplo, en algunos locales húngaros, [a-z]partidos endzs
Stéphane Chazelas
12

Porque *coincide con cero o más repeticiones del átomo anterior, y todos los motores de expresiones regulares intentan encontrar la primera coincidencia. Hay una subcadena de exactamente cero letras al comienzo de su cadena, por lo que es donde coincide. En el caso de que la cadena comience con una letra, *coincide tanto como sea posible, pero esto es secundario para encontrar la coincidencia más a la izquierda.

Las coincidencias de longitud cero pueden ser un poco problemáticas y, como viste, la solución es modificar el patrón para que requiera al menos un carácter. Con expresiones regulares extendidas, podrías +para eso:sed -E 's/[a-z]+/SUB/'

Por diversión, prueba:

echo 'less than 123 words' | sed 's/[0-9]*/x/g'
ilkkachu
fuente