Usar match para encontrar subcadenas en cadenas con solo bash


Aunque estoy casi seguro de que esto ha sido cubierto, parece que no puedo encontrar nada específico para esto. A medida que continúo mi viaje en el aprendizaje de bash sigo encontrando partes donde estoy desconcertado en cuanto a por qué las cosas suceden de la manera en que lo hacen.

Buscar y reemplazar o simplemente hacer coincidir sub-cadenas en cadenas es probablemente una de las primeras cosas que haces al escribir scripts. Pero, tratar de atenerse a un solo idioma o conjunto de herramientas es difícil de hacer en bash, ya que son capaces de resolver la mayoría de los problemas de múltiples maneras. Estoy haciendo todo lo posible para mantenerme lo más bajo posible con Bash. Me he encontrado con un problema que necesito que alguien me explique.

Hacer una búsqueda de sub-string en bash con match me da resultados diferentes dependiendo de la expresión regular que use, y no estoy seguro de por qué.

#!/bin/bash
Stext="Hallo World"
echo `expr "$Stext" : '^\(.[a-z]*\)'` # Hallo
echo `expr "$Stext" : '.*World'`      # 11

Aunque ambos buscan una palabra, creo, ambos no devuelven lo que encuentran. ¿Por qué?

Author: Kirby, 2012-03-07

4 answers

Ambas expresiones son equivalentes, la diferencia es la expresión regular que usa:

$ echo `expr "$Stext" : '^\(.[a-z]*\)'`
Hallo
$ echo `expr "$Stext" : '^.[a-z]*'`
5
$ echo `expr "$Stext" : '\(.*World\)'`
Hallo World
$ echo `expr "$Stext" : '.*World'`
11

Como puede ver, los paréntesis son lo que hace la diferencia para devolver la longitud de la coincidencia o la coincidencia en sí.

Puede encontrar más ejemplos en Capítulo 10 de la Guía Avanzada de Bash-Scripting.

 24
Author: jcollado,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-07 08:07:38

Puede usar la variable BASH_REMATCH en bash para obtener la cadena coincidente:

$ Stext="Hallo World"
$ [[ $Stext =~ ^.[a-z]* ]] && echo $BASH_REMATCH
Hallo
$ [[ $Stext =~ ^(.[a-z]*) ]] && echo ${BASH_REMATCH[1]}
Hallo

Las subcadenas que coinciden con subexpresiones entre paréntesis dentro de la expresión regular se guardan en la variable de matriz BASH_REMATCH. El elemento de BASH_REMATCH con índice 0 es la porción de la cadena que coincide con toda la expresión regular. El elemento de BASH_REMATCH con índice n es la porción de la cadena que coincide con la enésima subexpresión entre paréntesis.

 54
Author: kev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-12 15:36:31

Hice esta función simple:

match() {
    TRUE=1
    FALSE=0
    match_return=0
    echo $1 | grep $2 >/dev/null
    [ $? -eq 0 ] && match_return=$TRUE || match_return=$FALSE
}

Uso:

match Testing Test ; [ $match_return -eq 1 ] && echo "match!" || echo "nope"

Código completo: https://gist.github.com/TeeBSD/5121b3711fad40a09455

 0
Author: Antonio Feitosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-28 01:52:48

Para búsquedas rápidas de cadenas ... Una opción es grep.
Si no se encuentra, devuelve vacío, de lo contrario es una coincidencia:

found=`echo $big | grep -e $short`

if [ ! -z $found ]; then echo 'There is a match'; else echo 'No no'; fi
 0
Author: Sergio Abreu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-03 14:55:57