J'ai une chaîne dans Bash:
string="My string"
Comment puis-je tester s'il contient une autre chaîne?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Où ??
est mon opérateur inconnu. Dois-je utiliser l'écho et grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Cela semble un peu maladroit.
expr
commande iciRéponses:
Vous pouvez également utiliser la réponse de Marcus (* caractères génériques) en dehors d'une déclaration de cas, si vous utilisez des crochets doubles:
Notez que les espaces dans la chaîne d'aiguille doivent être placés entre guillemets doubles et les
*
caractères génériques doivent être à l'extérieur. Notez également qu'un opérateur de comparaison simple est utilisé (c'est-à-dire==
), et non l'opérateur regex=~
.la source
#!/bin/sh
. Essayez#!/bin/bash
plutôt.[[
. Voir ideone.com/ZSy1gZSi vous préférez l'approche regex:
la source
=~
opérateur recherche déjà une correspondance dans toute la chaîne; les.*
ici sont étrangers. De plus, les guillemets sont généralement préférables aux contre-obliques:[[ $string =~ "My s" ]]
E14)
. Il est probablement préférable d'affecter à une variable (à l'aide de guillemets), puis de comparer. Comme ça:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
c'est vrai.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Je ne suis pas sûr d'utiliser une instruction if, mais vous pouvez obtenir un effet similaire avec une instruction case:
la source
[[ $string == *foo* ]]
fonctionne également dans certaines versions sh conformes POSIX (par exemple/usr/xpg4/bin/sh
sur Solaris 10) et ksh (> = 88)[[
... le cas-switch a fonctionné!stringContain
variantes (compatibles ou indépendantes du boîtier)Comme ces réponses Stack Overflow parlent principalement de Bash , j'ai posté une fonction Bash indépendante de la casse tout en bas de cet article ...
Quoi qu'il en soit, il y a mon
Réponse compatible
Comme il y a déjà beaucoup de réponses en utilisant des fonctionnalités spécifiques à Bash, il existe un moyen de travailler sous des shells plus pauvres, comme BusyBox :
En pratique, cela pourrait donner:
Cela a été testé sous Bash, Dash , KornShell (
ksh
) et ash (BusyBox), et le résultat est toujours:En une seule fonction
Comme l'a demandé @EeroAaltonen, voici une version de la même démo, testée sous les mêmes shells:
Alors:
Remarque: vous devez échapper ou insérer des guillemets doubles et / ou des guillemets doubles:
Fonction simple
Cela a été testé sous BusyBox, Dash et, bien sûr, Bash:
Alors maintenant:
... Ou si la chaîne soumise pouvait être vide, comme l'a souligné @Sjlver, la fonction deviendrait:
ou comme suggéré par le commentaire d'Adrian Günter , en évitant les
-o
changements:Fonction finale (simple):
Et inverser les tests pour les rendre potentiellement plus rapides:
Avec des chaînes vides:
Indépendant du cas (Bash uniquement!)
Pour tester des chaînes sans se soucier de la casse, convertissez simplement chaque chaîne en minuscules:
Vérifier:
la source
string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; }
une dernière pensée: la chaîne vide contient-elle la chaîne vide? La version au dessus des choses oui (à cause de la-o -z "$1"
partie).Vous devez vous rappeler que les scripts shell sont moins un langage et plus une collection de commandes. Instinctivement, vous pensez que ce «langage» vous oblige à suivre un
if
avec un[
ou un[[
. Ces deux sont juste des commandes qui renvoient un état de sortie indiquant le succès ou l'échec (comme toutes les autres commandes). Pour cette raisongrep
, j'utiliserais , et non la[
commande.Faites juste:
Maintenant que vous envisagez de
if
tester l'état de sortie de la commande qui la suit (avec point-virgule), pourquoi ne pas reconsidérer la source de la chaîne que vous testez?L'
-q
option fait que grep ne produit rien, car nous voulons seulement le code retour.<<<
fait que le shell développe le mot suivant et l'utilise comme entrée de la commande, une version à une ligne du<<
document ici (je ne sais pas si c'est standard ou un bashisme).la source
if grep -q foo <(echo somefoothing); then
echo
n'est pas transférable, si vous passez une variable, utilisezprintf '%s' "$string
plutôt.grep -q foo <<<"$mystring"
implie une fourche et est bash etecho $mystring | grep -q foo
implie 2 fourchettes (un pour la conduite et la seconde pour la course/path/to/grep
)echo
sans indicateurs peut toujours avoir des problèmes de portabilité inattendus si la chaîne d'argument contient des séquences de barre oblique inverse.echo "nope\c"
est prévu sur certaines plates-formes pour fonctionner commeecho -e "nope"
sur d'autres.printf '%s' "nope"
vsprintf '%s\n' 'nope\c'
La réponse acceptée est la meilleure, mais comme il existe plusieurs façons de le faire, voici une autre solution:
${var/search/replace}
est$var
avec la première instance desearch
remplacée parreplace
, si elle est trouvée (elle ne change pas$var
). Si vous essayez de remplacerfoo
par rien et que la chaîne a changé, alors, évidemment, afoo
été trouvé.la source
Il existe donc de nombreuses solutions utiles à la question - mais laquelle est la plus rapide / utilise le moins de ressources?
Tests répétés en utilisant ce cadre:
Remplacement de TEST à chaque fois:
(doContain était dans la réponse de F. Houri)
Et pour les rires:
Ainsi, l'option de substitution simple l'emporte de manière prévisible que ce soit dans un test étendu ou dans un cas. L'affaire est portable.
Prévoir 100 000 greps est douloureusement prévisible! L'ancienne règle concernant l'utilisation d'utilitaires externes sans besoin est vraie.
la source
[[ $b == *$a* ]]
.case
gagne avec la plus petite consommation de temps globale. Il vous manque cependant un astérisque$b in *$a
. J'obtiens des résultats légèrement plus rapides pour[[ $b == *$a* ]]
que pourcase
avec le bug corrigé, mais cela peut dépendre aussi d'autres facteurs, bien sûr.[[ $b == *$a* ]]
est rapide etcase
presque aussi rapide (et agréablement compatible POSIX).Cela fonctionne également:
Et le test négatif est:
Je suppose que ce style est un peu plus classique - moins dépendant des fonctionnalités du shell Bash.
L'
--
argument est de la pure paranoïa POSIX, utilisé pour protéger contre les chaînes d'entrée similaires aux options, telles que--abc
ou-a
.Remarque: Dans une boucle étroite, ce code sera beaucoup plus lent que l'utilisation des fonctionnalités internes du shell Bash, car un (ou deux) processus distincts seront créés et connectés via des tuyaux.
la source
echo
n'est pas transférable, vous devriez utiliser à laprintf '%s' "$haystack
place.echo
tout simplement autre chose que du texte littéral sans échappements qui ne commence pas par un-
. Cela peut fonctionner pour vous, mais ce n'est pas portable. Même bashecho
se comportera différemment selon que l'xpg_echo
option est définie ou non. PS: j'ai oublié de fermer la double citation dans mon commentaire précédent.--
n'est pas répertorié dans la spécification POSIX pourprintf
, mais vous devezprintf '%s' "$anything"
quand même l' utiliser pour éviter les problèmes s'il$anything
contient un%
caractère.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 de 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:
Exemple 8, caractère générique .ext (insensible à la casse):
Prendre plaisir.
la source
Que dis-tu de ça:
la source
Comme Paul l'a mentionné dans sa comparaison de performances:
Ceci est conforme à POSIX comme le 'case "$ string" dans' la réponse fournie par Marcus , mais il est légèrement plus facile à lire que la réponse à la déclaration de cas. Notez également que cela sera beaucoup plus lent que l'utilisation d'une déclaration de cas. Comme l'a souligné Paul, ne l'utilisez pas en boucle.
la source
Cette réponse Stack Overflow était la seule à intercepter les caractères d'espace et de tiret:
la source
la source
echo "Couldn't find
instruction à la fin est une bonne astuce pour retourner 0 états de sortie pour ces commandes correspondantes.|| echo "Couldn't find"
vous retournerez un état de sortie d'erreur s'il n'y a pas de correspondance, ce que vous ne voudrez peut-être pas si vous exécutez un pipeline CI, par exemple où vous voulez que toutes les commandes retournent statuts de sortie sans erreurL'un est:
la source
expr
est l'un de ces utilitaires de couteau de l'armée suisse qui peut généralement faire tout ce que vous devez faire, une fois que vous avez compris comment le faire, mais une fois implémenté, vous ne vous souvenez plus pourquoi ni comment il fait ce qu'il fait, donc vous ne le touchez plus jamais, et espérez qu'il ne cesse de faire ce qu'il fait.expr
, à de rares occasions, lorsque la portabilité empêche d'utiliser bash (par exemple, un comportement incohérent dans les anciennes versions), tr (incohérent partout) ou sed (parfois trop lent). Mais par expérience personnelle, chaque fois queexpr
je relis ces -ismes, je dois retourner à la page de manuel. Donc, je voudrais simplement faire remarquer que chaque utilisation deexpr
être commentée ...expr
ettest
ont été mis en œuvre pour les exécuter. De nos jours, il existe généralement de meilleurs outils, dont beaucoup sont intégrés dans n'importe quelle coque moderne. Je suppose qu'iltest
est toujours là, mais personne ne semble manquerexpr
.J'aime sed.
Édition, logique:
Utilisez sed pour supprimer l'instance de sous-chaîne de la chaîne
Si la nouvelle chaîne diffère de l'ancienne chaîne, la sous-chaîne existe
la source
grep -q
est utile à cet effet.La même chose en utilisant
awk
:Production:
Production:
Source d'origine: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
la source
echo
n'est pas transférable, vous devriez utiliser à laprintf '%s' "$string"
place. J'édite la réponse car l'utilisateur ne semble plus exister.echo
pas portable, @ nyuszika7h?J'ai constaté que j'avais besoin de cette fonctionnalité assez fréquemment, donc j'utilise une fonction shell faite maison dans mon
.bashrc
comme celle-ci qui me permet de la réutiliser aussi souvent que nécessaire, avec un nom facile à retenir:Pour tester si
$string1
(par exemple, abc ) est contenu dans$string2
(par exemple, 123abcABC ), il me suffit d'exécuterstringinstring "$string1" "$string2"
et de vérifier la valeur de retour, par exemplela source
x
hack n'est requis que pour les très vieux obus.Mon .bash_profile fichier et comment j'ai utilisé grep:
Si la variable d'environnement PATH inclut mes deux
bin
répertoires, ne les ajoutez pas,la source
grep -q -E 'pattern1|...|patternN'
.Extension de la question répondue ici Comment savoir si une chaîne contient une autre chaîne dans POSIX sh? :
Cette solution fonctionne avec des caractères spéciaux:
la source
contains "-n" "n"
ne fonctionne pas ici, carecho -n
va avaler le-n
en option! Une solution populaire pour cela est d'utiliser à laprintf "%s\n" "$string"
place.Étant donné que la question POSIX / BusyBox est fermée sans fournir la bonne réponse (IMHO), je posterai une réponse ici.
La réponse la plus courte possible est:
ou
Notez que le double hachage est obligatoire avec certains shells (
ash
). Ci-dessus évaluera[ stringvalue ]
quand la sous-chaîne n'est pas trouvée. Il ne renvoie aucune erreur. Lorsque la sous-chaîne est trouvée, le résultat est vide et il est évalué[ ]
. Cela générera le code d'erreur 1 car la chaîne est complètement remplacée (en raison de*
).La syntaxe la plus courte et la plus courante:
ou
Un autre:
ou
Notez le seul signe égal!
la source
Correspondance exacte des mots:
la source
Essayez oobash.
Il s'agit d'une bibliothèque de chaînes de style OO pour Bash 4. Elle prend en charge les trémas allemands. Il est écrit en Bash.
De nombreuses fonctions sont disponibles:
-base64Decode
,-base64Encode
,-capitalize
,-center
,-charAt
,-concat
,-contains
,-count
,-endsWith
,-equals
,-equalsIgnoreCase
,-reverse
,-hashCode
,-indexOf
,-isAlnum
,-isAlpha
,-isAscii
,-isDigit
,-isEmpty
,-isHexDigit
,-isLowerCase
,-isSpace
,-isPrintable
,-isUpperCase
,-isVisible
,-lastIndexOf
,-length
,-matches
,-replaceAll
,-replaceFirst
,-startsWith
,-substring
,-swapCase
,-toLowerCase
,-toString
,-toUpperCase
,-trim
et-zfill
.Regardez l' exemple contient :
oobash est disponible sur Sourceforge.net .
la source
J'utilise cette fonction (une dépendance non incluse mais évidente). Il passe les tests ci-dessous. Si la fonction renvoie une valeur> 0, la chaîne a été trouvée. Vous pouvez tout aussi bien retourner 1 ou 0 à la place.
la source
Il s'agit de la même réponse que https://stackoverflow.com/a/229585/11267590 . Mais un style simple et également compatible POSIX.
la source
Cela trouvera toute occurrence de a ou b ou c
la source
L' exemple générique de meule de foin à aiguilles suit avec des variables
la source