web-dev-qa-db-fra.com

Comment savoir si une chaîne contient une autre chaîne dans POSIX sh?

Je veux écrire un script Unix Shell qui fera la logique si il y a une chaîne à l'intérieur d'une autre chaîne. Par exemple, si je suis dans un certain dossier, déconnectez-vous. Quelqu'un pourrait-il s'il vous plaît me dire comment y parvenir? Si possible, j'aimerais que cela ne soit pas spécifique à Shell (c'est-à-dire pas seulement bash), mais s'il n'y a pas d'autre moyen de me débrouiller avec cela.

#!/usr/bin/env sh

if [ "$PWD" contains "String1" ]
then
    echo "String1 present"
Elif [ "$PWD" contains "String2" ]
then
    echo "String2 present"
else
    echo "Else"
fi
116
Matt

Voici encore une autre solution. Ceci utilise expansion du paramètre de sous-chaîne POSIX , donc cela fonctionne en bash, dash, ksh ...

test "${string#*$Word}" != "$string" && echo "$Word found in $string"

Edit: C'est une bonne idée, C. Ross. Voici une version fonctionnalisée avec quelques exemples:

# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
    string="$1"
    substring="$2"
    if test "${string#*$substring}" != "$string"
    then
        return 0    # $substring is in $string
    else
        return 1    # $substring is not in $string
    fi
}

contains "abcd" "e" || echo "abcd does not contain e"
contains "abcd" "ab" && echo "abcd contains ab"
contains "abcd" "bc" && echo "abcd contains bc"
contains "abcd" "cd" && echo "abcd contains cd"
contains "abcd" "abcd" && echo "abcd contains abcd"
contains "" "" && echo "empty string contains empty string"
contains "a" "" && echo "a contains empty string"
contains "" "a" || echo "empty string does not contain a"
contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef"
contains "abcd efgh" " " && echo "abcd efgh contains a space"
142
fjarlq

Pure POSIX Shell:

#!/bin/sh
CURRENT_DIR=`pwd`

case "$CURRENT_DIR" in
  *String1*) echo "String1 present" ;;
  *String2*) echo "String2 present" ;;
  *)         echo "else" ;;
esac

Les shells étendus comme ksh ou bash ont des mécanismes d'appariement sophistiqués, mais l'ancien style case est étonnamment puissant.

71
Norman Ramsey

Malheureusement, je ne suis pas au courant d'un moyen de faire cela en sh. Cependant, en utilisant bash (à partir de la version 3.0.0, ce qui est probablement le cas), vous pouvez utiliser l'opérateur = ~ comme ceci:

#!/bin/bash
CURRENT_DIR=`pwd`

if [[ "$CURRENT_DIR" =~ "String1" ]]
then
 echo "String1 present"
Elif [[ "$CURRENT_DIR" =~ "String2" ]]
then
 echo "String2 present"
else
 echo "Else"
fi

En tant que bonus supplémentaire (et/ou un avertissement, si vos chaînes contiennent des caractères amusants), = ~ accepte les expressions rationnelles comme opérande correct, si vous omettez les guillemets.

38
John Hyland
#!/usr/bin/env sh

# Searches a subset string in a string:
# 1st arg:reference string
# 2nd arg:subset string to be matched

if echo "$1" | grep -q "$2"
then
    echo "$2 is in $1"
else 
    echo "$2 is not in $1"
fi
26
a.saurabh

Voici un lien vers diverses solutions à votre problème.

Ceci est mon préféré car il a le sens le plus lisible:

La méthode Star Wildcard

if [[ "$string" == *"$substring"* ]]; then
    return 1
fi
return 0
16
TT4M.C
case $(pwd) in
  *path) echo "ends with path";;
  path*) echo "starts with path";;
  *path*) echo "contains path";;
  *) echo "this is the default";;
esac
14
helpermethod

Il y a expression rationnelle bash . Ou il y a 'expr':

 if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
6
bmargulies

Dans les cas spéciaux où vous voulez savoir si un mot est contenu dans un texte long, vous pouvez parcourir le texte long avec une boucle.

found=F
query_Word=this
long_string="many many words in this text"
for w in $long_string; do
    if [ "$w" = "$query_Word" ]; then
          found=T
          break
    fi
done

Ceci est pur Bourne Shell.

2
Kemin Zhou

Voir la page de manuel pour le programme 'test'. Si vous ne testez que l'existence d'un répertoire, vous ferez normalement quelque chose comme ceci:

if test -d "String1"; then
  echo "String1 present"
end

Si vous essayez réellement de faire correspondre une chaîne, vous pouvez également utiliser les règles de développement bash et les caractères génériques:

if test -d "String*"; then
  echo "A directory starting with 'String' is present"
end

Si vous devez faire quelque chose de plus complexe, vous devrez utiliser un autre programme comme expr.

2
jdeseno

Si vous voulez une méthode ksh seulement aussi rapide que "test", vous pouvez faire quelque chose comme:

contains() # haystack needle
{
    haystack=${1/$2/}
    if [ ${#haystack} -ne ${#1} ] ; then
        return 1
    fi
    return 0
}

Cela fonctionne en supprimant l'aiguille dans la botte de foin, puis en comparant la longueur de la chaîne d'anciennes et de nouvelles bottes de foin.

1
JoeOfTex
test $(echo "stringcontain" "ingcon" |awk '{ print index($1, $2) }') -gt 0 && echo "String 1 contain string 2"

-> sortie: la chaîne 1 contient la chaîne 2

1
user5047266