2010-05-13 23 views
85

Ich möchte ein Unix-Shell-Skript schreiben, das verschiedene Logik ausführt, wenn eine Zeichenfolge innerhalb einer anderen Zeichenfolge ist. Zum Beispiel, wenn ich in einem bestimmten Ordner bin, verzweigen. Kann mir bitte jemand sagen, wie ich das erreichen soll? Wenn es möglich ist, möchte ich dies nicht Shell-spezifisch machen (d. H. Nicht nur Bash), aber wenn es keinen anderen Weg gibt, kann ich damit auskommen.Wie erkennen Sie, ob eine Zeichenfolge eine andere Zeichenfolge in Unix-Shell-Skripten enthält?

#!/usr/bin/env sh 

if [ "$PWD" contains "String1" ] 
then 
    echo "String1 present" 
elif [ "$PWD" contains "String2" ] 
then 
    echo "String2 present" 
else 
    echo "Else" 
fi 
+2

Ich weiß, das ist alt, aber hier sind ein paar Dinge für zukünftige Besucher zu beachten: (1) Es ist in der Regel gute Praxis, SNAKE_CASE Variablennamen für Umgebungs-und Shell-interne Variablen zu reservieren. (2) Einstellung von "CURRENT_DIR" ist redundant; Sie können einfach '$ PWD' verwenden. – nyuszika7h

Antwort

119

Hier ist noch eine andere Lösung. Dies verwendet POSIX substring parameter expansion, so dass es in bash arbeitet, Bindestriche KSH ...

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

Edit: Das ist eine großartige Idee, C. Ross. Hier ist eine funktionalisierte Version mit einigen Beispielen:

# 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" 
+2

clever, funktioniert auch mit [[]]. – Wyrmwood

+0

Ist hier ein Weg, um es zu machen, ohne Berücksichtigung der Groß- und Kleinschreibung? – CMCDragonkai

+3

Dies funktioniert nicht für mich, wenn Der Substring enthält Backslashes. Wie üblich speichert 'substring =" $ (printf '% q' "$ 2") "' den Tag. –

34

Leider ist mir nicht bewusst, eine Möglichkeit, dies in SH zu tun. Allerdings bash mit (ab Version 3.0.0, was wahrscheinlich ist, was Sie haben), können Sie den Operator = ~ wie folgt verwenden:

#!/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 

Als zusätzlichen Bonus (und/oder eine Warnung, wenn Ihr Zeichenfolgen haben irgendwelche lustigen Zeichen in ihnen, = ~ akzeptiert Regexe als den rechten Operanden, wenn Sie die Anführungszeichen weglassen.

+2

Zitiere nicht die Regex, sonst wird es * nicht * funktionieren. Versuchen Sie zum Beispiel "[[test = ~" test. * "]]' Vs. '[[test = ~ test. *]]'. – l0b0

+1

Nun, es wird gut funktionieren, wenn Sie für eine Teilzeichenfolge wie in der ursprünglichen Frage testen, aber es wird den rechten Operanden nicht als Regex behandeln. Ich werde meine Antwort aktualisieren, um das deutlicher zu machen. –

2

Siehe die Hilfeseite für das 'Test' Programm. Wenn Sie nur für die Existenz eines Verzeichnisses Testen Sie normalerweise so etwas wie dies tun:

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

Wenn Sie sich tatsächlich um eine Zeichenfolge zu entsprechen versuchen Sie bash Erweiterungsregeln & Platzhalter als auch verwenden können:

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

Wenn Sie etwas Komplexeres tun müssen, müssen Sie ein anderes Programm wie expr verwenden.

+1

Es scheint ein falsches Doppelzitat (") in Ihrem zweiten Beispiel zu sein. –

12
case $(pwd) in 
    *path) echo "ends with path";; 
    path*) echo "starts with path";; 
    *path*) echo "contains path";; 
    *) echo "this is the default";; 
esac 
55

rein POSIX-Shell:

#!/bin/sh 
CURRENT_DIR=`pwd` 

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

Erweitert Shells wie KSH oder bash hat Phantasie Anpassungsmechanismen, aber der alte Stil case ist überraschend stark.

18
#!/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 
+1

Ändern Sie' grep -q "$ 2" 'in' grep -q "$ 2">/dev/null', um unerwünschte Ausgabe zu vermeiden. –

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

-> Ausgang: String 1 enthalten String 2

1

Wenn Sie eine KSH wollen einzige Methode, die so schnell ist wie " Test ", können Sie etwas tun wie:

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

Es funktioniert durch Löschen der Nadel in der Heuhaufen und vergleichen Sie dann die Saitenlänge von alten und neuen Heuhaufen.

+1

Wäre es nicht möglich, das Ergebnis von 'test' zurückzugeben? Wie in' return [$ {# haystack} -eq $ {# 1}] '? –

10

Hier ist eine link zu verschiedenen Lösungen Ihres Problems.

Dies ist mein Favorit, da es die meisten Menschen lesbaren Sinn macht:

The Star Wildcard Methode

if [[ "$string" == *"$substring"* ]]; then 
    return 1 
fi 
return 0 
+0

Sehr schön, und sehr gut lesbar. – kiwicomb123

2

In besonderen Fällen, in denen Sie suchen möchten, ob ein Wort in einem langen enthalten ist Text, können Sie den langen Text mit einer Schleife durchlaufen.

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 

Dies ist reine Bourne-Shell.

Verwandte Themen