if["$x"="valid"];then
echo "x has the value 'valid'"fi
Si vous voulez faire quelque chose quand ils ne correspondent pas, remplacez-le =par !=. Vous pouvez en savoir plus sur les opérations de chaîne et les opérations arithmétiques dans leur documentation respective.
Pourquoi utilisons-nous des guillemets $x?
Vous voulez les guillemets $x, car s'il est vide, votre script Bash rencontre une erreur de syntaxe comme indiqué ci-dessous:
if[="valid"];then
Utilisation non standard de l' ==opérateur
Notez que Bash permet ==d'être utilisé pour l'égalité avec [, mais ce n'est pas standard .
Utilisez soit le premier cas où les guillemets autour $xsont facultatifs:
Comment cela se rapporte-t-il à la réponse acceptée donnée dans Erreur d'opérateur inattendue ? J'ai eu la même erreur lors de l'utilisation [ "$1" == "on" ]. La modification de ["$ 1" = "on"] a résolu le problème.
Piotr Dobrogost
78
Les espaces sont nécessaires.
TAAPSogeking
6
@JohnFeminella Lors de l'écriture dans un script bash, il doit avoir un seul =et non deux.
user13107
73
il convient de noter que vous ne pouvez pas utiliser [ $x -eq "valid" ]. -eqest l'opérateur de comparaison des entiers, pas des chaînes.
craq
2
@Alex, dans quels cas (si jamais) dois-je utiliser le modèle ["x$yes" == "xyes"], c'est-à-dire le préfixe de la variable et du littéral de chaîne avec un x? Est-ce une relique d'autrefois ou est-ce vraiment nécessaire dans certaines situations?
Merci pour la comparaison de l'ordre alphabétique des chaînes
shadi
Mon problème était que l' entourait $aréellement " "dans le cadre de la valeur littérale de la chaîne, j'ai donc dû utiliser le caractère d'échappement $bpour comparer les valeurs. J'ai pu le trouver après l'exécution bash -x ./script.sh, l'indicateur -x vous permet de voir la valeur de chaque exécution et aide au débogage.
ShahNewazKhan
Notez que la comparaison de l'ordre alphabétique n'est pas normalisée POSIX, il n'est donc pas garanti de fonctionner sur des plates-formes non GNU / des shells non-bash. Seules les opérations sur pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html sont garanties d'être portables.
Charles Duffy
62
Pour comparer des chaînes avec des caractères génériques, utilisez
if[["$stringA"==*$stringB*]];then# Do something hereelse# Do Something herefi
Il est important que les caractères génériques ne puissent être utilisés que du côté droit! Notez également les disparus "autour des caractères génériques. (btw: +1 pour les caractères génériques!)
Scz
6
L'expansion $stringBdoit être cité (et, soit dit en passant, le côté gauche n'a pas besoin d'être cité): if [[ $stringA = *"$stringB"* ]]; then.
gniourf_gniourf
j'essaye d'employer la même logique générique pour le nom de fichier dans le chemin de fichier. Mais ça ne marche pas pour moi. essayé toutes les différentes chaînes de caractères génériques fournies ici. mais ça va toujours à d'autre cas. stringA dans mon cas est un chemin de fichier / tmp / file et stringB est "file".
pluie
35
Je suis en désaccord avec l'un des commentaires sur un point:
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Non, ce n'est pas un oneliner fou
C'est juste que ça ressemble à un, hmm, les non-initiés ...
Il utilise des modèles communs comme une langue, en quelque sorte;
Et après avoir appris la langue.
En fait, c'est agréable à lire
Il s'agit d'une expression logique simple, avec une partie spéciale: l'évaluation paresseuse des opérateurs logiques.
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Chaque partie est une expression logique; le premier peut être vrai ou faux, les deux autres sont toujours vrais.
(["$x"=="valid"]&&
echo "valid")||
echo "invalid"
Maintenant, quand il est évalué, le premier est vérifié. S'il est faux, alors le deuxième opérande de la logique et&& après il n'est pas pertinent. Le premier n'est pas vrai, il ne peut donc pas être le premier et le second de toute façon.
Maintenant, dans ce cas, c'est le premier côté de la logique ou|| faux, mais cela pourrait être vrai si l'autre côté - la troisième partie - est vrai.
La troisième partie sera donc évaluée - principalement en écrivant le message comme un effet secondaire. (Il a le résultat 0pour true, que nous n'utilisons pas ici)
Les autres cas sont similaires, mais plus simples - et - je le promets! sont - peuvent être - faciles à lire!
(Je n'en ai pas, mais je pense qu'être un vétéran d'UNIX avec une barbe grise y contribue beaucoup.)
Le ... && ... || ...est généralement mal vu (désolé vétéran barbe grise d'Unix, vous vous trompez depuis tout ce temps), car il n'est pas sémantiquement équivalent à if ... then ... else .... Ne vous inquiétez pas, c'est un piège courant .
gniourf_gniourf
6
@gniourf_gniourf OP n'a pas tort - et ils ne sont probablement pas ignorants comme vous le suggérez. ... && ... || ...est un modèle parfaitement valide et un idiome bash commun. Son utilisation prescrit des connaissances préalables (ce qui peut être utile de garder à l'esprit s'il y a des débutants dans le public), mais OP a les cheveux pour prouver qu'ils savent comment éviter les couvercles de trous d'homme ouverts.
ebpa
3
@ebpa Que faire si l'instruction suivant && renvoie une valeur false, l'exécution se poursuivra jusqu'à l'instruction suivante || ? Si c'est le cas, c'est faux et c'est peut-être ce que suggère gniourf
TSG
4
Je pensais que l'écho n'était qu'un exemple. L'instruction suivant && pourrait toujours renvoyer une valeur non nulle
TSG
2
@gniourf_gniourf +1 pour avoir publié le lien vers Bash Pitfalls! Très utile!
Jaguar
21
vous pouvez également utiliser le cas d'utilisation / esac
@ytpillai, c'est l'équivalence. Gardez à l'esprit que les motifs peuvent être séparés par |, avant le ). L' ininstruction est équivalente à thendans les ifinstructions. Vous pourriez faire valoir que cela fonctionne sur une liste de modèles, où chaque liste a sa propre déclaration de quoi faire, si vous venez de Python. Pas comme substring in string, mais plutôt for item in list. Utilisez a *comme dernière instruction si vous souhaitez une elsecondition. Il revient à la première rencontre.
mazunki
18
Le script suivant lit un fichier nommé "testonthis" ligne par ligne, puis compare chaque ligne avec une chaîne simple, une chaîne avec des caractères spéciaux et une expression régulière. S'il ne correspond pas, le script imprimera la ligne, sinon non.
L'espace dans Bash est tellement important. Donc, ce qui suit fonctionnera:
["$LINE"!="table_name"]
Mais ce qui suit ne le fera pas:
["$LINE"!="table_name"]
Veuillez donc utiliser tel quel:
cat testonthis |while read LINE
doif["$LINE"!="table_name"]&&["$LINE"!="--------------------------------"]&&[["$LINE"=~[^[:space:]]]]&&[["$LINE"!= SQL*]];then
echo $LINE
fidone
Utilisez cette approche pour parcourir un fichier. Autrement dit, supprimez l'UUoC entre autres choses.
fedorqui 'SO arrête de nuire'
Ce n'est pas important à cause de bashmais parce que [c'est en fait un binaire externe (comme dans which [donne quelque chose comme /usr/bin/[)
Patrick Bergner
11
J'utiliserais probablement des correspondances d'expressions régulières si l'entrée n'a que quelques entrées valides. Par exemple, seuls "démarrer" et "arrêter" sont des actions valides.
Notez que je minuscule la variable $ACTIONen utilisant la virgule double. Notez également que cela ne fonctionnera pas sur les versions bash trop anciennes.
Exemples Bash 4+. Remarque: ne pas utiliser de guillemets entraînera des problèmes lorsque les mots contiennent des espaces, etc. Toujours citer dans Bash, IMO.
Voici quelques exemples dans Bash 4+:
Exemple 1, vérifiez «oui» dans la chaîne (insensible à la casse):
if[["${str,,}"==*"yes"*]];then
Exemple 2, vérifiez «oui» dans la chaîne (insensible à la casse):
pour moi (mac GNU bash version 4.4.12 (1) -release x86_64-apple-darwin17.0.0), je dois utiliser if [ "$a"="$b" ]ou cela ne fonctionne pas ... ne peut pas avoir d'espaces autour des égaux
spectre
1
Je l'ai fait de cette manière qui est compatible avec Bash et Dash (sh):
testOutput="my test"
pattern="my"case $testOutput in(*"$pattern"*)
echo "if there is a match"
exit 1;;(*)! echo there is no coincidence!;;esac
Réponses:
Utilisation de variables dans les instructions if
Si vous voulez faire quelque chose quand ils ne correspondent pas, remplacez-le
=
par!=
. Vous pouvez en savoir plus sur les opérations de chaîne et les opérations arithmétiques dans leur documentation respective.Pourquoi utilisons-nous des guillemets
$x
?Vous voulez les guillemets
$x
, car s'il est vide, votre script Bash rencontre une erreur de syntaxe comme indiqué ci-dessous:Utilisation non standard de l'
==
opérateurNotez que Bash permet
==
d'être utilisé pour l'égalité avec[
, mais ce n'est pas standard .Utilisez soit le premier cas où les guillemets autour
$x
sont facultatifs:ou utilisez le deuxième cas:
la source
[ "$1" == "on" ]
. La modification de ["$ 1" = "on"] a résolu le problème.=
et non deux.[ $x -eq "valid" ]
.-eq
est l'opérateur de comparaison des entiers, pas des chaînes.["x$yes" == "xyes"]
, c'est-à-dire le préfixe de la variable et du littéral de chaîne avec unx
? Est-ce une relique d'autrefois ou est-ce vraiment nécessaire dans certaines situations?Ou, si vous n'avez pas besoin d'une autre clause:
la source
echo
peut échouer.[ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid"
.{ echo invalid && false; }
est plus efficace que( echo invalid && false )
, car il évite de payer pour un sous-shell inutile.Remarques:
if
et[
et]
sont importants>
et<
sont des opérateurs de redirection donc échappez-lui avec\>
et\<
respectivement pour les chaînes.la source
$a
réellement" "
dans le cadre de la valeur littérale de la chaîne, j'ai donc dû utiliser le caractère d'échappement$b
pour comparer les valeurs. J'ai pu le trouver après l'exécutionbash -x ./script.sh
, l'indicateur -x vous permet de voir la valeur de chaque exécution et aide au débogage.Pour comparer des chaînes avec des caractères génériques, utilisez
la source
"
autour des caractères génériques. (btw: +1 pour les caractères génériques!)$stringB
doit être cité (et, soit dit en passant, le côté gauche n'a pas besoin d'être cité):if [[ $stringA = *"$stringB"* ]]; then
.Je suis en désaccord avec l'un des commentaires sur un point:
Non, ce n'est pas un oneliner fou
C'est juste que ça ressemble à un, hmm, les non-initiés ...
Il utilise des modèles communs comme une langue, en quelque sorte;
Et après avoir appris la langue.
En fait, c'est agréable à lire
Il s'agit d'une expression logique simple, avec une partie spéciale: l'évaluation paresseuse des opérateurs logiques.
Chaque partie est une expression logique; le premier peut être vrai ou faux, les deux autres sont toujours vrais.
Maintenant, quand il est évalué, le premier est vérifié. S'il est faux, alors le deuxième opérande de la logique et
&&
après il n'est pas pertinent. Le premier n'est pas vrai, il ne peut donc pas être le premier et le second de toute façon.Maintenant, dans ce cas, c'est le premier côté de la logique ou
||
faux, mais cela pourrait être vrai si l'autre côté - la troisième partie - est vrai.La troisième partie sera donc évaluée - principalement en écrivant le message comme un effet secondaire. (Il a le résultat
0
pour true, que nous n'utilisons pas ici)Les autres cas sont similaires, mais plus simples - et - je le promets! sont - peuvent être - faciles à lire!
(Je n'en ai pas, mais je pense qu'être un vétéran d'UNIX avec une barbe grise y contribue beaucoup.)
la source
... && ... || ...
est généralement mal vu (désolé vétéran barbe grise d'Unix, vous vous trompez depuis tout ce temps), car il n'est pas sémantiquement équivalent àif ... then ... else ...
. Ne vous inquiétez pas, c'est un piège courant .... && ... || ...
est un modèle parfaitement valide et un idiome bash commun. Son utilisation prescrit des connaissances préalables (ce qui peut être utile de garder à l'esprit s'il y a des débutants dans le public), mais OP a les cheveux pour prouver qu'ils savent comment éviter les couvercles de trous d'homme ouverts.vous pouvez également utiliser le cas d'utilisation / esac
la source
|
, avant le)
. L'in
instruction est équivalente àthen
dans lesif
instructions. Vous pourriez faire valoir que cela fonctionne sur une liste de modèles, où chaque liste a sa propre déclaration de quoi faire, si vous venez de Python. Pas commesubstring in string
, mais plutôtfor item in list
. Utilisez a*
comme dernière instruction si vous souhaitez uneelse
condition. Il revient à la première rencontre.Le script suivant lit un fichier nommé "testonthis" ligne par ligne, puis compare chaque ligne avec une chaîne simple, une chaîne avec des caractères spéciaux et une expression régulière. S'il ne correspond pas, le script imprimera la ligne, sinon non.
L'espace dans Bash est tellement important. Donc, ce qui suit fonctionnera:
Mais ce qui suit ne le fera pas:
Veuillez donc utiliser tel quel:
la source
bash
mais parce que[
c'est en fait un binaire externe (comme danswhich [
donne quelque chose comme/usr/bin/[
)J'utiliserais probablement des correspondances d'expressions régulières si l'entrée n'a que quelques entrées valides. Par exemple, seuls "démarrer" et "arrêter" sont des actions valides.
Notez que je minuscule la variable
$ACTION
en utilisant la virgule double. Notez également que cela ne fonctionnera pas sur les versions bash trop anciennes.la source
Exemples Bash 4+. Remarque: ne pas utiliser de guillemets entraînera des problèmes lorsque les mots contiennent des espaces, etc. Toujours citer dans Bash, IMO.
Voici quelques exemples dans Bash 4+:
Exemple 1, vérifiez «oui» dans la chaîne (insensible à la casse):
Exemple 2, vérifiez «oui» dans la chaîne (insensible à la casse):
Exemple 3, vérifiez «oui» dans la chaîne (sensible à la casse):
Exemple 4, vérifiez «oui» dans la chaîne (sensible à la casse):
Exemple 5, correspondance exacte (sensible à la casse):
Exemple 6, correspondance exacte (insensible à la casse):
Exemple 7, correspondance exacte:
Prendre plaisir.
la source
if [ "$a"="$b" ]
ou cela ne fonctionne pas ... ne peut pas avoir d'espaces autour des égauxJe l'ai fait de cette manière qui est compatible avec Bash et Dash (sh):
la source
(
et ne pas l'utiliser?