Confronto senza distinzione tra maiuscole e minuscole di stringhe nello script di shell


129

L' ==operatore viene utilizzato per confrontare due stringhe nello script di shell. Tuttavia, voglio confrontare due stringhe ignorando il caso, come si può fare? Esiste un comando standard per questo?

Risposte:


72

se hai la bash

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

altrimenti, dovresti dirci quale shell stai usando.

alternativa, usando awk

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

32
Per chiunque paragona le stringhe usando le ifistruzioni, l' shoptapproccio richiede di usare la [[ ]]forma a doppia parentesi di condizionale anziché la [ ]forma a parentesi singola . Vedi anche: gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
indiv

3
La domanda indica che ==viene utilizzato per confrontare due stringhe, ma la risposta dimostra un confronto senza distinzione tra maiuscole e minuscole utilizzando caseun'istruzione. Rassicurante, la shoptsoluzione consente anche l'uso-insensitive caso ==, =~e altri operatori di confronto stringa.
Taranaki,

7
Probabilmente saggio da eseguire shopt -u nocasematchdopo che il confronto è stato fatto al fine di ripristinare il valore predefinito di bash.
Ohad Schneider,

6
Meglio salvare e ripristinare l' nocasematchimpostazione. Prendilo con SHELLNOCASEMATCH=`shopt -p nocasematch`poi cambiarlo con shopt -s nocasematche una volta fatto, ripristinalo con$SHELLNOCASEMATCH
Urhixidur il

2
Meglio ancora:, SHELLNOCASEMATCH=$(shopt -p nocasematch; true)perché shopt -puscirà con il codice 1 se l'opzione non è impostata e questo può causare l'interruzione dello script se set -eè attiva.
Siamo tutti Monica il

158

In Bash, puoi utilizzare l'espansione dei parametri per modificare una stringa in tutte le lettere minuscole / maiuscole:

var1=TesT
var2=tEst

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

14
Almeno una risposta che non implica l'opzione shopt. Quindi puoi confrontare due stringhe ignorando case e nello stesso test, confrontane altre due con case. Grazie
jehon

37
È nuovo in Bash 4? Almeno in Bash 3.2.51 (usato in OS X 10.9) non funziona - la prima echoaffermazione risulta in:-bash: ${var1,,}: bad substitution
Felix Rabe,

1
Tali implementazioni di confronto senza distinzione tra maiuscole e minuscole sono soggette a problemi di localizzazione (come il problema I turco). Non so come shopt -s nocasematchsia implementato, ma di solito tali soluzioni "a livello di lingua" lo gestiscono correttamente.
Ohad Schneider,

5
@Ohad Schneider, lascia che i turchi si preoccupino dei problemi di localizzazione turca, ho solo bisogno di un modo rapido ed efficiente per abbinare la stringa e questo richiede la torta con il margine di
huuuuuge

1
utenti macOS, aggiorna la tua versione di Bash. A questo punto il tuo è obsoleto da oltre un decennio. itnext.io/upgrading-bash-on-macos-7138bd1066ba
Jason Carter

114

Tutte queste risposte ignorano il modo più semplice e veloce per farlo (purché tu abbia Bash 4):

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

Tutto quello che stai facendo è convertire entrambe le stringhe in minuscolo e confrontare i risultati.


6
Questo è disponibile solo in Bash 4 o più recente (ad es. Non su Mac OS X 10.11)
d4Rk,

8
@ d4Rk ed è per questo che la prima frase della mia risposta dice "fintanto che hai Bash 4". Detto questo, Bash 4 è in circolazione da oltre sette anni al momento in cui scrivo questo commento, e la mia installazione OS X lo ha avuto per quasi così tanto tempo.
Riot

@Riot mi dispiace, non l'ho notato in primo luogo. So che puoi installare tutto ciò che vuoi su OS X, ma il valore predefinito è 3.2 e poiché il mio script deve essere eseguito anche su diversi Mac, questa non è davvero un'opzione per me.
d4Rk,

2
@ d4Rk è comprensibile: se hai davvero bisogno di garantire la portabilità, suggerirei di attenersi allo standard shell POSIX, poiché in alcuni casi non sei sicuro di trovare alcuna versione di bash.
Riot

1
Questo e 'esattamente quello che stavo cercando. Dovrebbe essere più in alto =)
Robin Winslow,

39

Salvare lo stato di nocasematch (nel caso in cui un'altra funzione dipenda dal fatto che sia disabilitata):

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

Nota: utilizzare solo localse si trova all'interno di una funzione.


4
Bello perché le casedichiarazioni (comprese quelle nella risposta di ghostdog) mi faranno sempre strisciare la pelle
SeldomNeedy,

15

Un modo sarebbe convertire entrambe le stringhe in alto o in basso:

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

Un altro modo sarebbe usare grep:

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

Ho usato il trmetodo nelle mie applicazioni docker basate su alpine (che fornisce shvia busybox). Grazie.
MXWest,

7

Per la shell korn, uso il comando integrato di tipo (-l per le lettere minuscole e -u per le maiuscole).

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

2
Questo è molto meglio, in termini di prestazioni rispetto all'avvio di awk o di qualsiasi altro processo.
Alex

1
In bash, dichiarare -l o -u può essere usato per impostare gli attributi.
Bharat,

5

Molto facile se devi fare un confronto tra maiuscole e minuscole:

str1="MATCH"
str2="match"

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

Sarebbe meglio usare if fgrep -qix -- "$str1" <<<"$str2"; theninvece.

3

Ecco la mia soluzione 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

grepha un -iflag che significa che non fa distinzione tra maiuscole e minuscole, quindi chiedigli di dirti se var2 è in var1.

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

3
non funzionerà se ci sono caratteri speciali regex in var2.
Haridsv,

3

La zshsintassi è leggermente diversa, ma comunque più corta della maggior parte delle risposte qui:

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

Questo convertirà entrambe le stringhe in maiuscolo prima del confronto.


Un altro metodo utilizza zsh globbing flags, che ci consente di utilizzare direttamente la corrispondenza senza distinzione tra maiuscole e minuscole utilizzando il iflag glob:

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


1

Mi sono imbattuto in questo fantastico blog / tutorial / qualunque cosa abbia a che fare con il modello case sensitive . I seguenti tre metodi sono spiegati in dettaglio con esempi:

1. Converti il ​​motivo in minuscolo usando il 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. Usa regex con modelli di case

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. Attiva 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.