Comment puis-je écrire un script Shell qui fera une correspondance de sous-chaîne insensible à la casse de la sortie de la commande?
Voici d'abord un exemple de script simple qui n'ignore pas la casse:
#!/bin/bash
if [ $(echo hello) == hello ]; then
echo it works
fi
Essayez de changer la chaîne bonjour à droite, et elle ne devrait plus faire écho à it works
. Essayez de remplacer echo hello
Par une commande de votre choix. Si vous souhaitez ignorer la casse et qu'aucune chaîne ne contient de saut de ligne, vous pouvez utiliser grep:
#!/bin/bash
if echo Hello | grep -iqF hello; then
echo it works
fi
La clé ici est que vous dirigez une sortie de commande vers grep
. L'instruction if
teste l'état de sortie de la commande la plus à droite dans un pipeline - dans ce cas grep. Grep sort avec succès si et seulement s'il trouve une correspondance.
L'option -i
De grep dit d'ignorer la casse.
L'option -q
Dit de ne pas émettre de sortie et de quitter après la première correspondance.
L'option -F
Dit de traiter l'argument comme une chaîne plutôt que comme une expression régulière.
Notez que le premier exemple utilise [ expression ]
Qui permet des comparaisons directes et divers opérateurs utiles. Le second formulaire exécute simplement les commandes et teste leur état de sortie.
Vous pouvez faire une correspondance de sous-chaîne insensible à la casse en natif dans bash
en utilisant l'opérateur regex =~
si vous définissez l'option nocasematch
Shell. Par exemple
s1="hElLo WoRlD"
s2="LO"
shopt -s nocasematch
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
match
s1="gOoDbYe WoRlD"
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
no match
Pour une recherche de chaîne sensible à la casse de la valeur de la variable needle
dans la valeur de la variable haystack
:
case "$haystack" in
*"$needle"*) echo "present";
*) echo "absent";
esac
Pour une recherche de chaîne insensible à la casse, convertissez les deux dans la même casse.
uc_needle=$(printf %s "$needle" | tr '[:lower:]' '[:upper:]' ; echo .); uc_needle=${uc_needle%.}
uc_haystack=$(printf %s "$haystack" | tr '[:lower:]' '[:upper:]' ; echo .); uc_haystack=${uc_haystack%.}
case "$uc_haystack" in
*"$uc_needle"*) echo "present";;
*) echo "absent";;
esac
Notez que tr
in GNU coreutils ne prend pas en charge les paramètres régionaux multi-octets (par exemple UTF-8). Pour faire fonctionner les paramètres régionaux multi-octets, utilisez plutôt awk. Si vous allez pour utiliser awk, vous pouvez lui faire faire la comparaison de chaînes et pas seulement la conversion.
if awk 'BEGIN {exit !index(toupper(ARGV[2]), toupper(ARGV[1]))}' "$needle" "$haystack"; then
echo "present"
else
echo "absent"
fi
Le tr
de BusyBox ne prend pas en charge le [:CLASS:]
syntaxe; vous pouvez utiliser tr a-z A-Z
au lieu. BusyBox ne prend pas en charge les paramètres régionaux non ASCII.
Dans bash (mais pas sh), la version 4.0+, il existe une syntaxe intégrée pour la conversion de casse et une syntaxe plus simple pour la correspondance des chaînes.
if [[ "${haystack^^}" = *"${needle^^}"* ]]; then
echo "present"
else
echo "absent"
esac