J'ai le code
file="JetConst_reco_allconst_4j2t.png"
if [[ $file == *_gen_* ]];
then
echo "True"
else
echo "False"
fi
Je teste si file
contient "gen". La sortie est "False". Agréable!
Le problème est quand je remplace "gen" par une variable testseq
:
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file == *_$testseq_* ]];
then
echo "True"
else
echo "False"
fi
Maintenant, la sortie est "True". Comment est-ce possible? Comment resoudre le probleme?
Vous devez interpoler le $testseq
variable avec l'une des méthodes suivantes:
$file == *_"$testseq"_*
(ici $testseq
considéré comme une chaîne fixe)
$file == *_${testseq}_*
(ici $testseq
considéré comme un modèle).
Ou la _
immédiatement après le nom de la variable sera considéré comme faisant partie du nom de la variable (c'est un caractère valide dans un nom de variable).
Utilisez le =~
opérateur pour faire des comparaisons d'expressions régulières:
#!/bin/bash
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file =~ $testseq ]];
then
echo "True"
else
echo "False"
fi
De cette façon, il comparera si $file
a $testseq
sur son contenu.
user@Host:~$ ./string.sh
False
Si je change testseq="Const"
:
user@Host:~$ ./string.sh
True
Mais attention à ce que vous nourrissez $testseq
avec. Si la chaîne sur elle représente en quelque sorte une expression régulière (comme [0-9]
par exemple), il y a plus de chances de déclencher une "correspondance".
Référence :
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
case "$file" in
*_"$testseq"_*) echo 'True' ;;
*) echo 'False'
esac
En utilisant case ... esac
est l'un des moyens les plus simples d'effectuer une correspondance de modèle de manière portable. Il fonctionne comme une instruction "switch" dans d'autres langues (bash
, zsh
et ksh93
vous permet également de faire fall-through de différentes manières incompatibles). Les modèles utilisés sont les modèles de remplacement de nom de fichier standard.
Le problème que vous rencontrez est dû au fait que _
est un caractère valide dans un nom de variable. Le Shell verra ainsi *_$testseq_*
comme "*_
suivi de la valeur de la variable $testseq_
Et un *
". La variable $testseq_
n'est pas défini, il sera donc développé en une chaîne vide et vous vous retrouverez avec *_*
, qui correspond évidemment au $file
valeur que vous avez. Vous pouvez vous attendre à obtenir True
tant que le nom de fichier dans $file
contient au moins un trait de soulignement.
Pour délimiter correctement le nom de la variable, utilisez "..."
autour de l'expansion: *_"$testseq"_*
. Cela utiliserait la valeur de la variable comme chaîne. Souhaitez-vous utiliser la valeur de la variable comme modèle, utilisez *_${testseq}_*
au lieu.
Une autre solution rapide consiste à inclure les traits de soulignement dans la valeur de $testseq
:
testseq="_gen_"
puis utilisez simplement *"$testseq"*
comme modèle (pour une comparaison de chaînes).
Pour la méthode portable pour tester si une chaîne contient une sous-chaîne, utilisez:
file="JetConst_reco_allconst_4j2t.png"; testseq="gen"
[ "${file##*$testseq*}" ] || echo True Substring is present
Ou "${file##*"$testseq"*}"
pour éviter d'interpréter les caractères globaux dans testseq
.