Respondí esta pregunta en SuperUser que estaba relacionada con el tipo de expresiones regulares que se usaban al agrupar una salida.
La respuesta que di fue esta:
tail -f log | grep "some_string.*some_string"
Y luego, en tres comentarios a mi respuesta, @Bob escribió esto:
.*es codicioso y puede capturar más de lo que quieres..*?Suele ser mejor.
Luego esto,
el
?es un modificador activado*, lo que lo hace perezoso en lugar del codicioso predeterminado. Asumiendo PCRE.
Busqué en Google PCRE, pero no pude entender cuál es el significado de esto en mi respuesta.
y finalmente esto,
También debo señalar que esto es regex (grep haciendo POSIX regex por defecto), no un shell glob.
Solo sé qué es un Regex y su uso muy básico en el comando grep. Entonces, no pude obtener ninguno de esos 3 comentarios y tengo estas preguntas en mente:
- ¿Cuáles son las diferencias en el uso de
.*?frente.*? - ¿Cuál es mejor y bajo qué circunstancia? Por favor proporcione ejemplos.
También sería útil entender los comentarios, si alguien pudiera
ACTUALIZACIÓN: Como respuesta a la pregunta ¿En qué se diferencia Regex de Shell Globs? @Kusalananda proporcionó este enlace en su comentario.
NOTA: Si es necesario, lea mi respuesta a esta pregunta antes de responder para consultar el contexto.
fuente

.*vs..*?La pregunta "diferencia entre expresiones regulares y globos de shell" ya se ha abordado en este sitio.Respuestas:
Ashok ya señaló la diferencia entre
.*y.*?, así que solo proporcionaré información adicional.grep(suponiendo que la versión GNU) admite 4 formas de unir cadenas:grepusa BRE por defecto.BRE y ERE están documentados en el capítulo Expresiones regulares de POSIX y PCRE está documentado en su sitio web oficial . Tenga en cuenta que las características y la sintaxis pueden variar entre las implementaciones.
Vale la pena decir que ni BRE ni ERE admiten la pereza :
Entonces, si desea usar esa función, deberá usar PCRE en su lugar:
Editar 1
.*se usa para hacer coincidir el patrón "más largo" 1 posible..*?se utiliza para hacer coincidir el patrón "más corto" 1 posible.En mi experiencia, el comportamiento más buscado suele ser el segundo.
Por ejemplo, supongamos que tenemos la siguiente cadena y solo queremos hacer coincidir las etiquetas html 2 , no el contenido entre ellas:
Ahora compara
.*vs.*?:1. El significado de "más largo" y "más corto" en un contexto de expresiones regulares es un poco complicado, como señaló Kusalananda . Consulte la documentación oficial para más información.
2. No se recomienda analizar html con regex . Este es solo un ejemplo con fines educativos, no lo use en la producción.
fuente
.*vs.*??Supongamos que tomo una cadena como:
can cats eat plants?El uso de codicioso
c.*scoincidirá con toda la cadena, ya que comienzacy termina cons, siendo un operador codicioso, continúa coincidiendo hasta la aparición final de s.Mientras que usar el vago
c.*?ssolo coincidirá hasta que se encuentre la primera aparición des, es decir, cadenacan cats.A partir del ejemplo anterior, es posible que pueda reunir eso:
"Codicioso" significa hacer coincidir la cadena más larga posible. "Perezoso" significa hacer coincidir la cadena más corta posible. Adición de una
?a un cuantificador como*,+,?, o{n,m}hace que sea perezoso.fuente
cats, por lo que no se aplica estrictamente "lo más corto posible" en ese sentido.Una cadena podría coincidir de varias maneras (de simple a más compleja):
Como una cadena estática (Suponga var = '¡Hola Mundo!'):
shell
[ "$var" = "Hello World!" ] && echo yesgrep
echo "$var" | grep -F "Hello"bash
grep -F "Hello" <<<"$var"Como un pegote:
shell
echo ./*# enumera todos los archivos en pwd. golpe deconcha
case $var in (*Worl*) echo yes;; (*) echo no;; esac[[ "$var" == *"Worl"* ]] && echo yesHay globos básicos y extendidos. El
caseejemplo usa globos básicos. El[[ejemplo bash usa globos extendidos. La primera coincidencia de archivo podría ser básica o extendida en algún shell como la configuraciónextgloben bash. Ambos son idénticos en este caso. Grep no podía usar globos.El asterisco en un globo significa algo diferente a un asterisco en una expresión regular :
Glob
* matches any number (including none) ofcualquier personaje .regex
* matches any number (including none) of theelemento anterior .Como una expresión regular básica (BRE):
sed
echo "$var" | sed 's/W.*d//'# print: ¡Hola!grep
grep -o 'W.*d' <<<"$var"# print World!No hay BRE en shells (básicos) o awk.
Expresiones regulares extendidas (ERE):
bash
[[ "$var" =~ (H.*l) ]]# match: Hola Worlsed
echo "$var" | sed -E 's/(d|o)//g'# print: Hell Wrl!awk
awk '/W.*d/{print $1}' <<<"$var"# print: Holagrep
grep -oE 'H.*l' <<<"$var"# print: Hola WorlExpresiones regulares compatibles con Perl:
grep
grep -oP 'H.*?l# print: HelSolo en un PCRE a
*?tiene algún significado de sintaxis específica.Hace que el asterisco sea perezoso (sin gracia): pereza en lugar de avaricia .
Esto es solo la punta del iceberg, hay codiciosos, perezosos , dóciles o posesivos . También hay mirar hacia adelante y hacia atrás, pero no se aplican al asterisco
*.Hay una alternativa para obtener el mismo efecto que una expresión regular no codiciosa:
La idea es muy simple: no use un punto
., niegue el siguiente carácter para que coincida[^o]. Con una etiqueta web:Lo anterior debería aclarar completamente todos los comentarios de @Bob 3. Parafraseando:
.*es codicioso.*?no lo es.Preguntas
¿Cuáles son las diferencias en el uso de. ? vs. ?
.*?es válido solo en sintaxis PCRE..*es más portátil.[^a]*¿Cuál es mejor y bajo qué circunstancia? Por favor proporcione ejemplos.
¿Mejor? Depende de la meta. No hay mejor, cada uno es útil para diferentes propósitos. He proporcionado varios ejemplos arriba. ¿Necesitas más?
fuente