181 votes

Comparaison insensible à la casse des chaînes de caractères dans le shell script.

En == L'opérateur est utilisé pour comparer deux chaînes de caractères dans le shell script. Cependant, je veux comparer deux chaînes de caractères en ignorant la casse, comment faire ? Existe-t-il une commande standard pour cela ?

0 votes

Note rapide : Non, == es pas l'opérateur de comparaison standard des chaînes de caractères dans l'interpréteur de commandes ; le seul opérateur de comparaison normalisé par POSIX est = .

202voto

alphaniner Points 211

En Bash, vous pouvez utiliser l'expansion des paramètres pour modifier une chaîne en minuscules ou en majuscules :

var1=TesT
var2=tEst

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

17 votes

Au moins une réponse qui n'implique pas l'option "shopt". Ainsi, vous pouvez comparer deux chaînes sans tenir compte de la casse et, dans le même test, en comparer deux autres avec la casse. Merci

52 votes

Est-ce nouveau dans Bash 4 ? En tout cas, dans Bash 3.2.51 (utilisé dans OS X 10.9), cela ne fonctionne pas. echo Cette déclaration a pour résultat : -bash: ${var1,,}: bad substitution

1 votes

De telles implémentations de comparaison insensibles à la casse sont sujettes à des problèmes de localisation (comme le problème du I turc). Je ne sais pas comment shopt -s nocasematch est implémenté, mais en général, ces solutions "au niveau du langage" le gèrent correctement.

88voto

ghostdog74 Points 86060

Si vous avez bash

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

sinon, vous devez nous dire quel shell vous utilisez.

alternative, en utilisant awk

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

40 votes

Pour tous ceux qui comparent des chaînes de caractères en utilisant if les déclarations, les shopt Cette approche nécessite l'utilisation de l'équerre double. [[ ]] la forme conditionnelle au lieu de la forme à une seule parenthèse [ ] forme. Voir aussi : gnu.org/software/bash/manuel/html_node/The-Shopt-Builtin.html

4 votes

La question indique que == est utilisé pour comparer deux chaînes de caractères, mais la réponse montre une comparaison insensible à la casse en utilisant un mot clé case déclaration. De manière rassurante, le shopt permet également l'utilisation insensible à la casse des == , =~ et d'autres opérateurs de comparaison de chaînes de caractères.

13 votes

Il est probablement sage d'exécuter shopt -u nocasematch après que la comparaison soit faite afin de revenir à la valeur par défaut de bash.

45voto

Gerry Hickman Points 79

Sauvegarder l'état de nocasematch (au cas où une autre fonction dépendrait de sa désactivation) :

local orig_nocasematch=$(shopt -p nocasematch; true)
shopt -s nocasematch

[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"

$orig_nocasematch

Note que local n'est nécessaire qu'à l'intérieur d'une fonction.
En outre, le ; true empêchera le shell de se terminer lorsque set -e est en marche et $(shopt -p nocasematch) échoue (parce que nocasematch n'a PAS été défini du tout).

4 votes

C'est bien parce que case Les déclarations (y compris celles de la réponse de ghostdog) me donneront toujours la chair de poule.

0 votes

@Seldom'Where'sMonica'Needy, pourquoi ? case est conforme à la norme POSIX ; [[ ]] est une extension non standard. Du point de vue de la portabilité, case est la voie à suivre.

22voto

Randy Proctor Points 2331

Une façon de procéder serait de convertir les deux cordes en supérieures ou inférieures :

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

Un autre moyen serait d'utiliser grep :

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

1 votes

J'ai utilisé le tr dans mes applications dockerisées basées sur alpine (qui fournit sh via busybox ). Merci.

0 votes

test "$(...)" = "$(...)" -- les guillemets doubles ne sont pas facultatifs pour un fonctionnement correct avec toutes les chaînes possibles.

7voto

Ek C. Points 11

Pour le shell korn, j'utilise la commande intégrée de typographie (-l pour les minuscules et -u pour les majuscules).

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

2 votes

C'est bien mieux, en termes de performances, que de lancer awk ou tout autre processus.

1 votes

En bash, déclarer -l ou -u peut être utilisé pour définir les attributs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X