Je veux voir si une chaîne est à l'intérieur d'une partie d'une autre chaîne.
par exemple:
'ab' in 'abc' -> true
'ab' in 'bcd' -> false
Comment puis-je faire cela dans les conditions d'un script bash?
Vous pouvez utiliser le formulaire ${VAR/subs}
où VAR
contient la chaîne la plus grande et
subs
est la sous-chaîne que vous essayez de trouver:
my_string=abc
substring=ab
if [ "${my_string/$substring}" = "$my_string" ] ; then
echo "${substring} is not in ${my_string}"
else
echo "${substring} was found in ${my_string}"
fi
Cela fonctionne car ${VAR/subs}
est égal à $VAR
, mais la première occurrence de la chaîne subs
est supprimée, en particulier si $VAR
ne contient pas le mot subs
, il ne sera pas modifié.
[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]
les crochets sont pour le test, et comme il s’agit de crochets doubles, il peut donc contenir des tests supplémentaires comme =~
.
Pour que vous puissiez utiliser ce formulaire, quelque chose comme
var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
echo "pass"
else
echo "fail"
fi
Modifier: corrigé "= ~", s'était retourné.
Utilisation de modèles de nom de fichier de bash (modèles "glob")
substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no # no
Les deux approches suivantes fonctionneront dans tout environnement compatible POSIX, pas seulement dans bash:
substr=ab
for s in abc bcd; do
if case ${s} in *"${substr}"*) true;; *) false;; esac; then
printf %s\n "'${s}' contains '${substr}'"
else
printf %s\n "'${s}' does not contain '${substr}'"
fi
done
substr=ab
for s in abc bcd; do
if printf %s\n "${s}" | grep -qF "${substr}"; then
printf %s\n "'${s}' contains '${substr}'"
else
printf %s\n "'${s}' does not contain '${substr}'"
fi
done
Les deux sorties ci-dessus:
'abc' contains 'ab'
'bcd' does not contain 'ab'
Le premier a l'avantage de ne pas générer un processus distinct grep
.
Notez que j'utilise printf %s\n "${foo}"
au lieu de echo "${foo}"
car echo
pourrait modifier ${foo}
s'il contient des barres obliques inverses.
Il s’agit de la solution la plus portable, fonctionnera même sur les anciens shells Bourne et Korn
#!/bin/bash
case "abcd" in
*$1*) echo "It's a substring" ;;
*) echo "Not a substring" ;;
esac
Exemple d'analyse:
$ ./case_substr.sh "ab"
It's a substring
$ ./case_substr.sh "whatever"
Not a substring
Notez que vous n'avez pas à utiliser spécifiquement echo
, vous pouvez utiliser exit 1
et exit 0
pour indiquer le succès ou l'échec.
Ce que nous pourrions aussi faire, c’est créer une fonction (qui peut être utilisée dans de gros scripts si nécessaire) avec des valeurs de retour spécifiques (0 sur correspondance, 1 sur aucune correspondance):
$ ./substring_function.sh
ab is substring
$ cat substring_function.sh
#!/bin/sh
is_substring(){
case "$2" in
*$1*) return 0;;
*) return 1;;
esac
}
main(){
if is_substring "ab" "abcdefg"
then
echo "ab is substring"
fi
}
main [email protected]
$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"
it's a substring
Cette approche particulière est utile avec les instructions if-else dans bash
. Aussi principalement portable
$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"
it is a substring
$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring
$ ruby -e ' puts "is substring" if ARGV[1].include? ARGV[0]' "ab" "abcdef"
is substring
Attention aux [[
et "
:
[[ $a == z* ]] # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
[ $a == z* ] # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).
Comme l'a dit @glenn_jackman, mais sachez que si vous mettez tout le deuxième terme entre guillemets, le test passera à une correspondance littérale .
Source: lien
Semblable à la réponse d’edwin, mais avec une portabilité améliorée pour posix & ksh, et un toucher moins bruyant que celui de Richard:
substring=ab
string=abc
if [ "$string" != "${string%$substring*}" ]; then
echo "$substring IS in $string"
else
echo "$substring is NOT in $string"
fi
string=bcd
if [ "$string" != "${string%$substring*}" ]; then
echo "$string contains $substring"
else
echo "$string does NOT contain $substring"
fi
Sortie:
abc contains ab
bcd does NOT contain ab
Lire d'autres questions sur les étiquettes command-line bash scripts