Comparación entre mayúsculas y minúsculas de cadenas en script de shell


129

El ==operador se utiliza para comparar dos cadenas en el script de shell. Sin embargo, quiero comparar dos cadenas ignorando mayúsculas y minúsculas, ¿cómo se puede hacer? ¿Hay algún comando estándar para esto?

Respuestas:


72

si tienes bash

str1="MATCH"
str2="match"
shopt -s nocasematch
case "$str1" in
 $str2 ) echo "match";;
 *) echo "no match";;
esac

de lo contrario, debe decirnos qué shell está utilizando.

alternativa, usando awk

str1="MATCH"
str2="match"
awk -vs1="$str1" -vs2="$str2" 'BEGIN {
  if ( tolower(s1) == tolower(s2) ){
    print "match"
  }
}'

32
Para cualquier persona que compare cadenas que usan ifdeclaraciones, el shoptenfoque requiere que use la forma de doble [[ ]]condicional de condicional en lugar de la forma de un solo corchete [ ]. Ver también: gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
— indiv

3
La pregunta indica que ==se usa para comparar dos cadenas, pero la respuesta demuestra una comparación que no distingue entre mayúsculas y minúsculas mediante una caseinstrucción. De modo tranquilizador, la shoptsolución también permite el uso de mayúsculas y minúsculas de ==, =~y otros operadores de comparación de cadenas.
— taranaki

77
Probablemente sea prudente ejecutar shopt -u nocasematchdespués de que se realice la comparación para volver al valor predeterminado de bash.
— Ohad Schneider

66
Lo mejor es guardar y restaurar la nocasematchconfiguración. Agárralo y SHELLNOCASEMATCH=`shopt -p nocasematch`luego shopt -s nocasematch$SHELLNOCASEMATCH
— cámbialo

2
Mejor aún: SHELLNOCASEMATCH=$(shopt -p nocasematch; true)porque shopt -psaldrá con el código 1 si la opción no está configurada, y esto puede hacer que el script se cancele si set -eestá vigente.
— Todos somos Mónica

158

En Bash, puede usar la expansión de parámetros para modificar una cadena en minúsculas / mayúsculas:

var1=TesT
var2=tEst

echo ${var1,,} ${var2,,}
echo ${var1^^} ${var2^^}

14
Al menos una respuesta que no implique la opción de compra. Entonces puede comparar dos cadenas ignorando mayúsculas y minúsculas y en la misma prueba, compare otras dos con mayúsculas y minúsculas. Gracias
— jehon

37
¿Es esto nuevo en Bash 4? Al menos en Bash 3.2.51 (usado en OS X 10.9) no funciona - la primera echodeclaración da como resultado:-bash: ${var1,,}: bad substitution
— Felix Rabe

1
Tales implementaciones de comparación que no distinguen entre mayúsculas y minúsculas son propensas a problemas de localización (como el problema turco I). No sé cómo shopt -s nocasematchse implementa, pero por lo general, estas soluciones de "nivel de lenguaje" lo manejan correctamente.
— Ohad Schneider

55
@Ohad Schneider, deje que los turcos se preocupen por los problemas de localización turcos, solo necesito una forma rápida y eficiente de unir las cuerdas y esto toma el pastel por un margen
— huuuuuge

1
Usuarios de macOS, actualicen su versión de Bash. El tuyo está más de una década desactualizado en este momento. itnext.io/upgrading-bash-on-macos-7138bd1066ba
— Jason Carter

114

Todas estas respuestas ignoran la forma más fácil y rápida de hacer esto (siempre que tenga Bash 4):

if [ "${var1,,}" = "${var2,,}" ]; then
  echo ":)"
fi

Todo lo que está haciendo allí es convertir ambas cadenas a minúsculas y comparar los resultados.


66
Esto solo está disponible en Bash 4 o más reciente (por ejemplo, no en Mac OS X 10.11)
— d4Rk

8
@ d4Rk, razón por la cual la primera oración de mi respuesta dice "siempre que tenga Bash 4". Dicho esto, Bash 4 ha estado fuera durante más de siete años al momento de escribir este comentario, y mi propia instalación de OS X lo ha tenido durante casi ese tiempo.
— Riot

@Riot lo siento, no lo noté en primer lugar. Sé que puedes instalar cualquier bash que quieras en OS X, pero el valor predeterminado es 3.2 y como mi script también debe ejecutarse en diferentes Mac, esta no es realmente una opción para mí.
— d4Rk

2
@ d4Rk es comprensible: si realmente necesita garantizar la portabilidad, le sugiero que se adhiera al estándar de shell POSIX, ya que no está garantizado que encuentre ninguna versión de bash en algunos casos.
— Disturbios

1
Esto es exactamente lo que estaba buscando. Debería estar más arriba =)
— Robin Winslow

39

Guarde el estado de nocasematch (en caso de que alguna otra función dependa de que esté deshabilitada):

local orig_nocasematch=$(shopt -p nocasematch)
shopt -s nocasematch
[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"
$orig_nocasematch

Nota: solo use localsi está dentro de una función.


44
Agradable porque las casedeclaraciones (incluidas las de la respuesta de ghostdog) siempre harán que mi piel se
— erice

15

Una forma sería convertir ambas cadenas en superior o inferior:

test $(echo "string" | /bin/tr '[:upper:]' '[:lower:]') = $(echo "String" | /bin/tr '[:upper:]' '[:lower:]') && echo same || echo different

Otra forma sería usar grep:

echo "string" | grep -qi '^String$' && echo same || echo different

Utilicé el trmétodo en mis aplicaciones Docker-Iized basadas en Alpine (que proporciona a shtravés de busybox). Gracias.
— MXWest

7

Para korn shell, uso el comando integrado typeset (-l para minúsculas y -u para mayúsculas).

var=True
typeset -l var
if [[ $var == "true" ]]; then
    print "match"
fi

2
Esto es mucho mejor, en términos de rendimiento, que iniciar awk o cualquier otro proceso.
— Alex

1
En bash, declare -l o -u se puede usar para establecer los atributos.
— Bharat

5

Muy fácil si fgrep para hacer una línea que distingue entre mayúsculas y minúsculas compare:

str1="MATCH"
str2="match"

if [[ $(fgrep -ix $str1 <<< $str2) ]]; then
    echo "case-insensitive match";
fi

Sería mejor usarlo if fgrep -qix -- "$str1" <<<"$str2"; thenen su lugar.

3

Aquí está mi solución usando tr:

var1=match
var2=MATCH
var1=`echo $var1 | tr '[A-Z]' '[a-z]'`
var2=`echo $var2 | tr '[A-Z]' '[a-z]'`
if [ "$var1" = "$var2" ] ; then
  echo "MATCH"
fi

3

greptiene una -ibandera que significa que no distingue entre mayúsculas y minúsculas, así que pídele que te diga si var2 está en var1.

var1=match 
var2=MATCH 
if echo $var1 | grep -i "^${var2}$" > /dev/null ; then
    echo "MATCH"
fi

3
no funcionará si hay caracteres especiales de expresiones regulares en var2.
— haridsv

3

Para zshla sintaxis es un poco diferente, pero sigue siendo más corta que la mayoría de las respuestas aquí:

> str1='mAtCh'
> str2='MaTcH'
> [[ "$str1:u" = "$str2:u" ]] && echo 'Strings Match!'
Strings Match!
>

Esto convertirá ambas cadenas a mayúsculas antes de la comparación.


Otro método hace uso de zsh's globbing flags, que nos permite hacer uso directo de la coincidencia entre mayúsculas y minúsculas mediante el uso de la ibandera global:

setopt extendedglob
[[ $str1 = (#i)$str2 ]] && echo "Match success"
[[ $str1 = (#i)match ]] && echo "Match success"


1

Me encontré con este gran blog / tutorial / lo que sea sobre tratar con un patrón sensible a mayúsculas y minúsculas . Los siguientes tres métodos se explican en detalle con ejemplos:

1. Convertir el patrón a minúsculas usando el comando tr

opt=$( tr '[:upper:]' '[:lower:]' <<<"$1" )
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other options"
                ;;
esac

2. Use expresiones regulares con patrones de casos

opt=$1
case $opt in
        [Ss][Qq][Ll])
                echo "Running mysql backup using mysqldump tool..."
                ;;
        [Ss][Yy][Nn][Cc])
                echo "Running backup using rsync tool..."
                ;;
        [Tt][Aa][Rr])
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

3. Encienda nocasematch

opt=$1
shopt -s nocasematch
case $opt in
        sql)
                echo "Running mysql backup using mysqldump tool..."
                ;;
        sync)
                echo "Running backup using rsync tool..."
                ;;
        tar)
                echo "Running tape backup using tar tool..."
                ;;
        *)
                echo "Other option"
                ;;
esac

shopt -u nocasematch
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.