Ich habe eine Zeichenfolge in Bash:
string="My string"
Wie kann ich testen, ob eine andere Zeichenfolge enthalten ist?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Wo ??
mein unbekannter Operator ist. Benutze ich echo und grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Das sieht etwas unbeholfen aus.
Sie können auch Marcus 'Antwort (* Wildcards) außerhalb einer case-Anweisung verwenden, wenn Sie doppelte Klammern verwenden:
string='My long string'
if [[ $string == *"My long"* ]]; then
echo "It's there!"
fi
Beachten Sie, dass Leerzeichen in der Nadelkette zwischen Anführungszeichen gesetzt werden müssen und die *
-Platzhalterzeichen außerhalb liegen müssen.
Wenn Sie den Regex-Ansatz bevorzugen:
string='My string';
if [[ $string =~ .*My.* ]]
then
echo "It's there!"
fi
Ich bin nicht sicher, ob Sie eine if-Anweisung verwenden, aber Sie können einen ähnlichen Effekt mit einer case-Anweisung erzielen:
case "$string" in
*foo*)
# Do stuff
;;
esac
Da es bereits viele Antworten mit Bash-spezifischen Funktionen gibt, gibt es eine Möglichkeit, unter ärmeren Shells zu arbeiten, wie busybox :
[ -z "${string##*$reqsubstr*}" ]
In der Praxis könnte dies Folgendes ergeben:
string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
if [ -z "${string##*$reqsubstr*}" ] ;then
echo "String '$string' contain substring: '$reqsubstr'."
else
echo "String '$string' don't contain substring: '$reqsubstr'."
fi
done
Dies wurde unter bash , dash , ksh und ash (busybox) getestet. Das Ergebnis ist immer:
String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.
Wie von @EeroAaltonen gefragt, ist hier eine Version derselben Demo, die unter den gleichen Shells getestet wurde:
myfunc() {
reqsubstr="$1"
shift
string="[email protected]"
if [ -z "${string##*$reqsubstr*}" ] ;then
echo "String '$string' contain substring: '$reqsubstr'.";
else
echo "String '$string' don't contain substring: '$reqsubstr'."
fi
}
Dann:
$ myfunc 'o "M' 'echo "My String"'
String 'echo "My String"' contain substring 'o "M'.
$ myfunc 'alt' 'echo "My String"'
String 'echo "My String"' don't contain substring 'alt'.
Hinweis: Sie müssen Anführungszeichen und/oder doppelte Anführungszeichen setzen oder einschließen:
$ myfunc 'o "M' echo "My String"
String 'echo My String' don't contain substring: 'o "M'.
$ myfunc 'o "M' echo \"My String\"
String 'echo "My String"' contain substring: 'o "M'.
Dies wurde unter busybox , dash und natürlich bash getestet:
stringContain() { [ -z "${2##*$1*}" ]; }
Das war's Leute!
Dann jetzt:
$ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi
no
$ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi
yes
... oder wenn die übergebene Zeichenfolge leer sein könnte, wie von @Sjlver gezeigt, würde die Funktion zu:
stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }
oder wie von Adrian Günters Kommentar vorgeschlagen , -o
-Umschaltung vermeiden:
stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ] ;} ; }
Mit leeren Zeichenketten:
$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no
Sie sollten sich daran erinnern, dass Shell-Scripting weniger eine Sprache als eine Sammlung von Befehlen ist. Instinktiv denken Sie, dass diese "Sprache" verlangt, dass Sie einer if
mit einem [
oder einem [[
folgen. Bei beiden Befehlen handelt es sich lediglich um Befehle, die einen Exit-Status zurückgeben, der auf Erfolg oder Misserfolg hinweist (wie bei jedem anderen Befehl). Aus diesem Grund würde ich grep
verwenden und nicht den [
-Befehl.
Mach einfach:
if grep -q foo <<<"$string"; then
echo "It's there"
fi
Nun, da Sie an if
denken, wie Sie den Exit-Status des nachfolgenden Befehls prüfen (komplett mit Semikolon). Warum nicht die Quelle der Zeichenfolge, die Sie testen, noch einmal überdenken?
## Instead of this
filetype="$(file -b "$1")"
if grep -q "tar archive" <<<"$filetype"; then
#...
## Simply do this
if file -b "$1" | grep -q "tar archive"; then
#...
Die -q
-Option bewirkt, dass grep nichts ausgibt, da nur der Rückgabecode gewünscht wird. <<<
bewirkt, dass die Shell das nächste Word erweitert und als Eingabe für den Befehl verwendet, eine einzeilige Version des <<
-Dokuments (ich bin nicht sicher, ob dies Standard oder ein Bashmus ist).
Die akzeptierte Antwort ist am besten, aber da es mehr als einen Weg gibt, dies zu tun, gibt es eine andere Lösung:
if [ "$string" != "${string/foo/}" ]; then
echo "It's there!"
fi
${var/search/replace}
ist $var
, wobei die erste Instanz von search
durch replace
ersetzt wird, falls sie gefunden wird ($var
wird nicht geändert). Wenn Sie versuchen, foo
durch nichts zu ersetzen, und die Zeichenfolge geändert wurde, wurde offensichtlich foo
gefunden.
Es gibt also viele nützliche Lösungen für die Frage - aber welche ist am schnellsten/nutzt die geringste Ressource?
Wiederholte Tests mit diesem Rahmen:
/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'
TEST jedes Mal ersetzen:
[[ $b =~ $a ]] 2.92user 0.06system 0:02.99elapsed 99%CPU
[ "${b/$a//}" = "$b" ] 3.16user 0.07system 0:03.25elapsed 99%CPU
[[ $b == *$a* ]] 1.85user 0.04system 0:01.90elapsed 99%CPU
case $b in *$a):;;esac 1.80user 0.02system 0:01.83elapsed 99%CPU
doContain $a $b 4.27user 0.11system 0:04.41elapsed 99%CPU
(doContain war in F. Houris Antwort)
Und zum Kichern:
echo $b|grep -q $a 12.68user 30.86system 3:42.40elapsed 19%CPU !ouch!
So gewinnt die einfache Substitutionsoption prädikativ, ob in einem erweiterten Test oder in einem Fall. Der Fall ist tragbar.
Das Ausleiten auf 100000 Greps ist vorhersehbar schmerzhaft! Die alte Regel über die Verwendung externer Dienstprogramme ohne Notwendigkeit gilt.
Das funktioniert auch:
if printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
printf "Found needle in haystack"
fi
Und der negative Test ist:
if ! printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
echo "Did not find needle in haystack"
fi
Ich nehme an, dass dieser Stil etwas klassischer ist - weniger von den Eigenschaften von Bash Shell abhängig.
Das --
-Argument ist reine POSIX-Paranoia und wird verwendet, um gegen Eingabezeichenfolgen zu schützen, die Optionen wie --abc
oder -a
ähneln.
Hinweis: In einer engen Schleife ist dieser Code viel langsamer als die Verwendung interner Bash Shell-Funktionen, da ein (oder zwei) separate Prozesse erstellt und über Pipes miteinander verbunden werden.
Wie wäre es damit:
text=" <tag>bmnmn</tag> "
if [[ "$text" =~ "<tag>" ]]; then
echo "matched"
else
echo "not matched"
fi
Wie Paulus in seinem Leistungsvergleich erwähnte:
if echo "abcdefg" | grep -q "bcdef"; then
echo "String contains is true."
else
echo "String contains is not true."
fi
Dies ist POSIX-konform wie die Antwort "case" $ string "in" von Marcus, ist jedoch etwas einfacher zu lesen als die Antwort in der case-Anweisung. Beachten Sie auch, dass dies viel langsamer ist als die Verwendung einer case-Anweisung. Verwenden Sie sie, wie Paulus betont hat, nicht in einer Schleife.
Bash4 + Beispiele. Hinweis: Wenn Sie keine Anführungszeichen verwenden, führt dies zu Problemen, wenn Wörter Leerzeichen usw. enthalten. Zitieren Sie immer in bash IMO.
Hier einige Beispiele für BASH4 +:
Beispiel 1, überprüfen Sie 'Ja' in Zeichenfolge (Groß- und Kleinschreibung wird nicht berücksichtigt):
if [[ "${str,,}" == *"yes"* ]] ;then
Beispiel 2, überprüfen Sie 'Ja' in Zeichenfolge (Groß- und Kleinschreibung wird nicht berücksichtigt):
if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then
Beispiel 3, überprüfen Sie 'Ja' in der Zeichenfolge (Groß- und Kleinschreibung beachten):
if [[ "${str}" == *"yes"* ]] ;then
Beispiel 4, überprüfen Sie 'Ja' in der Zeichenfolge (Groß- und Kleinschreibung beachten):
if [[ "${str}" =~ "yes" ]] ;then
Beispiel 5, genaue Übereinstimmung (Groß- und Kleinschreibung beachten):
if [[ "${str}" == "yes" ]] ;then
Beispiel 6, exakte Übereinstimmung (Groß- und Kleinschreibung wird nicht berücksichtigt):
if [[ "${str,,}" == "yes" ]] ;then
Beispiel 7, genaue Übereinstimmung:
if [ "$a" = "$b" ] ;then
Beispiel 8, Platzhalterübereinstimmung .ext (Groß- und Kleinschreibung wird nicht berücksichtigt):
if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then
genießen.
Diese Stack Overflow-Antwort war der einzige, der Leerzeichen einfängt und Striche anlegt:
# For null cmd arguments checking
to_check=' -t'
space_n_dash_chars=' -'
[[ $to_check == *"$space_n_dash_chars"* ]] && echo found
Eins ist:
[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' || echo 'no'
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"
grep -q
ist für diesen Zweck nützlich.
Dasselbe mit awk
:
string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'
Ausgabe:
Nicht gefunden
string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'
Ausgabe:
Gefunden
Originalquelle: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
Mein .bash_profile und wie ich grep Verwendet habe, wenn der PATH meine 2 bin-Verzeichnisse enthielt, hängen Sie sie nicht an
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
U=~/.local.bin:~/bin
if ! echo "$PATH" | grep -q "home"; then
export PATH=$PATH:${U}
fi
Ich mag sed.
substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1
Bearbeiten, Logik:
Verwenden Sie sed, um die Instanz der Teilzeichenfolge aus der Zeichenfolge zu entfernen
Wenn die neue Zeichenfolge von der alten Zeichenfolge abweicht, ist eine Teilzeichenfolge vorhanden
Ich habe diese Funktionalität ziemlich häufig benötigt, daher verwende ich in meinem .bashrc
eine selbstgebaute Shell-Funktion, die es mir erlaubt, sie so oft wie nötig wiederzuverwenden, mit einem leicht zu merkenden Namen:
function stringinstring()
{
case "$2" in
*"$1"*)
return 0
;;
esac
return 1
}
Um zu testen, ob $string1
(etwa abc ) in $string2
(beispielsweise 123abcABC ) enthalten ist, muss ich nur stringinstring "$string1" "$string2"
ausführen und beispielsweise den Rückgabewert prüfen
stringinstring "$str1" "$str2" && echo YES || echo NO
Probieren Sie oobash aus. Dies ist eine OO-ähnliche String-Bibliothek für Bash 4. Sie unterstützt deutsche Umlaute. Es ist in Bash geschrieben. Viele Funktionen stehen zur Verfügung: -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
, -zfill
, ,CODE__.
Schauen Sie sich das Beispiel an:
[Desktop]$ String a testXccc
[Desktop]$ a.contains tX
true
[Desktop]$ a.contains XtX
false
Genaue Wortübereinstimmung:
string='My long string'
exactSearch='long'
if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1
then
echo "It's there"
fi
Ich benutze diese Funktion (eine Abhängigkeit ist nicht enthalten, aber offensichtlich). Es besteht die unten gezeigten Tests. Wenn die Funktion einen Wert> 0 zurückgibt, wurde der String gefunden. Sie können stattdessen auch 1 oder 0 zurückgeben.
function str_instr {
# Return position of ```str``` within ```string```.
# >>> str_instr "str" "string"
# str: String to search for.
# string: String to search.
typeset str string x
# Behavior here is not the same in bash vs ksh unless we escape special characters.
str="$(str_escape_special_characters "${1}")"
string="${2}"
x="${string%%$str*}"
if [[ "${x}" != "${string}" ]]; then
echo "${#x} + 1" | bc -l
else
echo 0
fi
}
function test_str_instr {
str_instr "(" "'[email protected] (dev,web)'" | assert_eq 11
str_instr ")" "'[email protected] (dev,web)'" | assert_eq 19
str_instr "[" "'[email protected] [dev,web]'" | assert_eq 11
str_instr "]" "'[email protected] [dev,web]'" | assert_eq 19
str_instr "a" "abc" | assert_eq 1
str_instr "z" "abc" | assert_eq 0
str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7
str_instr "a" "" | assert_eq 0
str_instr "" "" | assert_eq 0
str_instr " " "Green Eggs" | assert_eq 6
str_instr " " " Green " | assert_eq 1
}
Erweiterung der hier beantworteten Frage https://stackoverflow.com/a/8811800/712666
Diese Lösung arbeitet mit Sonderzeichen:
# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
string="$1"
substring="$2"
if echo "$string" | $(type -p ggrep grep | head -1) -F -- "$substring" >/dev/null; 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"
contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]"
contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]"
contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*"
contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h"
contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"