it-swarm.com.de

Wie kann man in bash feststellen, ob eine Zeichenfolge eine Teilzeichenfolge einer anderen ist?

Ich möchte sehen, ob sich eine Zeichenfolge in einem Teil einer anderen Zeichenfolge befindet.
z.B.:

'ab' in 'abc' -> true
'ab' in 'bcd' -> false

Wie kann ich dies unter der Bedingung eines Bash-Skripts tun?

49
Lucio

Sie können das Formular ${VAR/subs} verwenden, wobei VAR die größere Zeichenfolge enthält und subs die Teilzeichenfolge ist, die Sie suchen:

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

Dies funktioniert, weil ${VAR/subs} gleich $VAR ist, aber mit dem ersten Vorkommen der Zeichenfolge subs entfernt wurde, insbesondere wenn $VAR nicht das Wort subs enthält wird nicht geändert.

27
edwin

[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]

die Klammern sind für den Test, und da es sich um doppelte Klammern handelt, können einige zusätzliche Tests wie =~ durchgeführt werden.

Sie könnten dieses Formular also so ähnlich verwenden

var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
    echo "pass"
else
    echo "fail"
fi

Edit: korrigiert "= ~", war umgedreht.

47
demure

Verwenden von bash Dateinamenmuster (aka "glob" -Muster)

substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no    # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no    # no
12
glenn jackman

Die folgenden zwei Ansätze funktionieren in jeder POSIX-kompatiblen Umgebung, nicht nur in 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

Beide der obigen Ausgaben:

'abc' contains 'ab'
'bcd' does not contain 'ab'

Ersteres hat den Vorteil, dass kein separater grep -Prozess gestartet wird.

Beachten Sie, dass ich printf %s\\n "${foo}" anstelle von echo "${foo}" verwende, da echo möglicherweise ${foo} verfälscht, wenn es umgekehrte Schrägstriche enthält.

10
Richard Hansen

Shell case statement

Dies ist die portabelste Lösung, die auch auf alten Bourne-Shells und Korn-Shell funktioniert

#!/bin/bash
case "abcd" in
    *$1*) echo "It's a substring" ;;
    *) echo "Not a substring" ;;
esac

Probelauf:

$ ./case_substr.sh "ab"                                                                                           
It's a substring
$ ./case_substr.sh "whatever"                                                                                     
Not a substring

Beachten Sie, dass Sie echo nicht speziell verwenden müssen. Sie können exit 1 und exit 0 verwenden, um Erfolg oder Misserfolg anzuzeigen.

Wir könnten auch eine Funktion erstellen (die bei Bedarf in großen Skripten verwendet werden kann) mit bestimmten Rückgabewerten (0 bei Übereinstimmung, 1 bei keiner Übereinstimmung):

$ ./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

Dieser spezielle Ansatz ist nützlich für if-else-Anweisungen in bash. Meistens auch tragbar

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
6

Achte auf den [[ und ":

[[ $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).

Also, wie @glenn_jackman sagte, aber beachten Sie, dass, wenn Sie den gesamten zweiten Term in doppelte Anführungszeichen setzen, der Test auf Literal Matching umschaltet.

Quelle: http://tldp.org/LDP/abs/html/comparison-ops.html

5
Campa

Ähnlich wie Edwins Antwort, jedoch mit verbesserter Portabilität für posix & ksh und einem Hauch weniger laut als bei 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

Ausgabe:

abc contains ab
bcd does NOT contain ab
4
laubster