Comment déterminer si une chaîne est une sous-chaîne d'une autre dans bash?

45

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?

    
posée Lucio 25.05.2013 - 01:35
la source

7 réponses

24

Vous pouvez utiliser le formulaire ${VAR/subs}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é.

    
réponse donnée edwin 25.05.2013 - 01:54
la source
43

[[ "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é.

    
réponse donnée demure 25.05.2013 - 01:56
la source
12

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
    
réponse donnée glenn jackman 25.05.2013 - 20:12
la source
10

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.

    
réponse donnée Richard Hansen 30.05.2013 - 01:01
la source
6

instruction de cas de shell

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

$ 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

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             
it is a substring

Python

$ 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

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             
is substring
    
réponse donnée Sergiy Kolodyazhnyy 24.12.2016 - 22:33
la source
5

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

    
réponse donnée Campa 29.05.2013 - 08:36
la source
3

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
    
réponse donnée laubster 07.01.2015 - 18:42
la source

Lire d'autres questions sur les étiquettes