In welcher Beziehung steht das zu der akzeptierten Antwort in Unerwarteter Bedienerfehler ? Ich habe den gleichen Fehler bei der Verwendung [ "$1" == "on" ]. Durch Ändern von ["$ 1" = "on"] wurde das Problem behoben.
Piotr Dobrogost
78
Die Räume werden benötigt.
TAAPSogeking
6
@ JohnFeminella Wenn Sie in ein Bash-Skript schreiben, sollte es ein einzelnes =und nicht zwei haben.
user13107
73
Es könnte erwähnenswert sein, dass Sie nicht verwenden können [ $x -eq "valid" ]. -eqist der Vergleichsoperator für Ganzzahlen, nicht für Zeichenfolgen.
Craq
2
@Alex, In welchen Fällen (wenn überhaupt) muss ich das Muster verwenden ["x$yes" == "xyes"], bei dem sowohl der Variablen als auch dem Zeichenfolgenliteral ein vorangestellt wird x? Ist das ein Relikt aus alten Zeiten oder wird es in manchen Situationen wirklich gebraucht?
Vielen Dank für den Vergleich der alphabetischen Reihenfolge der Zeichenfolge
Shadi
Mein Problem war, dass es $atatsächlich " "als Teil des String-Literalwerts umgeben war, daher musste ich das Escape-Zeichen verwenden $b, um die Werte zu vergleichen. Ich konnte dies nach dem Ausführen feststellen bash -x ./script.sh. Mit dem Flag -x können Sie den Wert jeder Ausführung anzeigen und beim Debuggen helfen.
ShahNewazKhan
Beachten Sie, dass der alphabetische Reihenfolgevergleich nicht POSIX-standardisiert ist, sodass nicht garantiert werden kann, dass er auf Nicht-GNU-Plattformen / Nicht-Bash-Shells funktioniert. Nur die Vorgänge unter pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html sind garantiert portabel.
Charles Duffy
62
Verwenden Sie zum Vergleichen von Zeichenfolgen mit Platzhaltern
if[["$stringA"==*$stringB*]];then# Do something hereelse# Do Something herefi
Es ist wichtig, dass die Platzhalter nur auf der rechten Seite verwendet werden können! Beachten Sie auch die fehlenden "Platzhalter. (Übrigens: +1 für Platzhalter!)
Scz
6
Die Erweiterung $stringBmuss angegeben werden (und im Übrigen muss die linke Seite nicht angegeben werden) : if [[ $stringA = *"$stringB"* ]]; then.
gniourf_gniourf
Ich versuche, die gleiche Platzhalterlogik für den Dateinamen im Dateipfad zu verwenden. Aber es funktioniert nicht bei mir. habe alle hier angegebenen Platzhalterzeichenfolgen ausprobiert. aber es geht immer um sonst fall. stringA ist in meinem Fall ein Dateipfad / tmp / file und stringB ist "file".
Regen
35
Ich muss einem der Kommentare in einem Punkt widersprechen:
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Nein, das ist kein verrückter Oneliner
Es sieht nur so aus, als würde man, hmm, den Uneingeweihten ...
In gewisser Weise werden gemeinsame Muster als Sprache verwendet.
Und nachdem du die Sprache gelernt hast.
Eigentlich ist es schön zu lesen
Es ist ein einfacher logischer Ausdruck mit einem besonderen Teil: der verzögerten Auswertung der Logikoperatoren.
["$x"=="valid"]&& echo "valid"|| echo "invalid"
Jeder Teil ist ein logischer Ausdruck; Das erste kann wahr oder falsch sein, die anderen beiden sind immer wahr.
(["$x"=="valid"]&&
echo "valid")||
echo "invalid"
Wenn es nun ausgewertet wird, wird das erste geprüft. Wenn es falsch ist, ist der zweite Operand der Logik und&& danach nicht relevant. Das erste ist nicht wahr, also kann es sowieso nicht das erste und das zweite wahr sein.
Nun, in diesem Fall ist die erste Seite der Logik oder|| falsch, aber es könnte wahr sein, wenn die andere Seite - der dritte Teil - wahr ist.
Daher wird der dritte Teil bewertet - hauptsächlich das Schreiben der Nachricht als Nebeneffekt. (Es hat das Ergebnis 0für wahr, das wir hier nicht verwenden)
Die anderen Fälle sind ähnlich, aber einfacher - und - das verspreche ich! sind - können - leicht zu lesen sein!
(Ich habe keine, aber ich denke, ein UNIX-Veteran mit grauem Bart zu sein, hilft dabei sehr.)
Das ... && ... || ...ist normalerweise verpönt (sorry, Unix-Veteran mit grauem Bart, Sie haben sich die ganze Zeit geirrt), da es semantisch nicht äquivalent zu ist if ... then ... else .... Keine Sorge, dies ist eine häufige Gefahr .
gniourf_gniourf
6
@gniourf_gniourf OP ist nicht falsch - noch sind sie wahrscheinlich unwissend, wie Sie vorschlagen. ... && ... || ...ist ein vollkommen gültiges Muster und eine gängige Bash-Sprache. Die Verwendung setzt Vorkenntnisse voraus (was gut zu beachten ist, wenn Anfänger im Publikum sind), aber OP hat die Haare, um zu beweisen, dass sie wissen, wie man offene Schachtabdeckungen vermeidet.
Ebpa
3
@ebpa Was passiert, wenn die Anweisung nach && den Wert false zurückgibt, wird die Ausführung mit der Anweisung nach || fortgesetzt ? Wenn ja, ist das falsch und vielleicht ist es das, was gniourf vorschlägt
TSG
4
Ich dachte, Echo sei nur ein Beispiel. Die Anweisung nach && gibt möglicherweise immer noch einen Wert ungleich Null zurück
TSG
2
@gniourf_gniourf +1 für das Posten des Links zu Bash Pitfalls! Sehr hilfreich!
@ytpillai, es ist Äquivalenz. Denken Sie daran, dass Sie Muster durch |, vor dem trennen können ). Die inAnweisung entspricht thenin ifAnweisungen. Sie könnten argumentieren, dass es über eine Liste von Mustern funktioniert, wobei jede Liste ihre eigene Erklärung hat, was zu tun ist, wenn Sie aus Python stammen. Nicht wie substring in string, sondern for item in list. Verwenden Sie a *als letzte Anweisung, wenn Sie eine elseBedingung wünschen . Es kehrt bei der ersten Begegnung zurück.
Mazunki
18
Das folgende Skript liest zeilenweise aus einer Datei mit dem Namen "testonthis" und vergleicht dann jede Zeile mit einer einfachen Zeichenfolge, einer Zeichenfolge mit Sonderzeichen und einem regulären Ausdruck. Wenn es nicht übereinstimmt, druckt das Skript die Zeile, andernfalls nicht.
Platz in Bash ist so wichtig. Also wird folgendes funktionieren:
["$LINE"!="table_name"]
Aber das wird nicht:
["$LINE"!="table_name"]
Verwenden Sie also bitte unverändert:
cat testonthis |while read LINE
doif["$LINE"!="table_name"]&&["$LINE"!="--------------------------------"]&&[["$LINE"=~[^[:space:]]]]&&[["$LINE"!= SQL*]];then
echo $LINE
fidone
Verwenden Sie diesen Ansatz , um eine Datei zu durchsuchen. Entfernen Sie unter anderem die UUoC.
Fedorqui 'SO hör auf zu schaden'
Es ist nicht wichtig, weil, bashsondern weil [es sich tatsächlich um eine externe Binärdatei handelt (wie in which [ergibt so etwas wie /usr/bin/[)
Patrick Bergner
11
Ich würde wahrscheinlich Regexp-Übereinstimmungen verwenden, wenn die Eingabe nur wenige gültige Einträge enthält. ZB sind nur "Start" und "Stopp" gültige Aktionen.
Beachten Sie, dass ich die Variable $ACTIONmit Doppelkommas in Kleinbuchstaben schreibe. Beachten Sie auch, dass dies bei zu alten Bash-Versionen nicht funktioniert.
Bash 4+ Beispiele. Hinweis: Wenn Sie keine Anführungszeichen verwenden, treten Probleme auf, wenn Wörter Leerzeichen usw. enthalten. Zitieren Sie immer in Bash, IMO.
Hier sind einige Beispiele in Bash 4+:
Beispiel 1: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
if[["${str,,}"==*"yes"*]];then
Beispiel 2: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
Für mich (Mac GNU Bash Version 4.4.12 (1) -release x86_64-apple-darwin17.0.0) muss ich verwenden if [ "$a"="$b" ]oder es funktioniert nicht ... kann keine Leerzeichen um das Gleiche haben
Spektrum
1
Ich habe es auf diese Weise gemacht, die mit Bash und Dash (sh) kompatibel ist :
testOutput="my test"
pattern="my"case $testOutput in(*"$pattern"*)
echo "if there is a match"
exit 1;;(*)! echo there is no coincidence!;;esac
Antworten:
Verwenden von Variablen in if-Anweisungen
Wenn Sie etwas tun möchten, wenn es nicht übereinstimmt, ersetzen Sie es
=
durch!=
. Weitere Informationen zu Zeichenfolgenoperationen und arithmetischen Operationen finden Sie in der jeweiligen Dokumentation.Warum verwenden wir Anführungszeichen
$x
?Sie möchten die Anführungszeichen verwenden
$x
, da Ihr Bash-Skript, wenn es leer ist, auf einen Syntaxfehler stößt, wie unten dargestellt:Nicht standardmäßige Verwendung des
==
BedienersBeachten Sie, dass Bash
==
für die Gleichstellung mit verwendet werden[
kann, dies ist jedoch kein Standard .Verwenden Sie entweder den ersten Fall, in dem die Anführungszeichen
$x
optional sind:oder verwenden Sie den zweiten Fall:
quelle
[ "$1" == "on" ]
. Durch Ändern von ["$ 1" = "on"] wurde das Problem behoben.=
und nicht zwei haben.[ $x -eq "valid" ]
.-eq
ist der Vergleichsoperator für Ganzzahlen, nicht für Zeichenfolgen.["x$yes" == "xyes"]
, bei dem sowohl der Variablen als auch dem Zeichenfolgenliteral ein vorangestellt wirdx
? Ist das ein Relikt aus alten Zeiten oder wird es in manchen Situationen wirklich gebraucht?Oder wenn Sie keine else-Klausel benötigen:
quelle
echo
dies fehlschlagen kann.[ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid"
.{ echo invalid && false; }
ist effizienter als( echo invalid && false )
, da keine unnötige Subshell bezahlt werden muss.Anmerkungen:
if
und[
und]
sind wichtig>
und<
sind Umleitungsoperatoren so entkommen sie mit\>
und\<
jeweils für Streicher.quelle
$a
tatsächlich" "
als Teil des String-Literalwerts umgeben war, daher musste ich das Escape-Zeichen verwenden$b
, um die Werte zu vergleichen. Ich konnte dies nach dem Ausführen feststellenbash -x ./script.sh
. Mit dem Flag -x können Sie den Wert jeder Ausführung anzeigen und beim Debuggen helfen.Verwenden Sie zum Vergleichen von Zeichenfolgen mit Platzhaltern
quelle
"
Platzhalter. (Übrigens: +1 für Platzhalter!)$stringB
muss angegeben werden (und im Übrigen muss die linke Seite nicht angegeben werden) :if [[ $stringA = *"$stringB"* ]]; then
.Ich muss einem der Kommentare in einem Punkt widersprechen:
Nein, das ist kein verrückter Oneliner
Es sieht nur so aus, als würde man, hmm, den Uneingeweihten ...
In gewisser Weise werden gemeinsame Muster als Sprache verwendet.
Und nachdem du die Sprache gelernt hast.
Eigentlich ist es schön zu lesen
Es ist ein einfacher logischer Ausdruck mit einem besonderen Teil: der verzögerten Auswertung der Logikoperatoren.
Jeder Teil ist ein logischer Ausdruck; Das erste kann wahr oder falsch sein, die anderen beiden sind immer wahr.
Wenn es nun ausgewertet wird, wird das erste geprüft. Wenn es falsch ist, ist der zweite Operand der Logik und
&&
danach nicht relevant. Das erste ist nicht wahr, also kann es sowieso nicht das erste und das zweite wahr sein.Nun, in diesem Fall ist die erste Seite der Logik oder
||
falsch, aber es könnte wahr sein, wenn die andere Seite - der dritte Teil - wahr ist.Daher wird der dritte Teil bewertet - hauptsächlich das Schreiben der Nachricht als Nebeneffekt. (Es hat das Ergebnis
0
für wahr, das wir hier nicht verwenden)Die anderen Fälle sind ähnlich, aber einfacher - und - das verspreche ich! sind - können - leicht zu lesen sein!
(Ich habe keine, aber ich denke, ein UNIX-Veteran mit grauem Bart zu sein, hilft dabei sehr.)
quelle
... && ... || ...
ist normalerweise verpönt (sorry, Unix-Veteran mit grauem Bart, Sie haben sich die ganze Zeit geirrt), da es semantisch nicht äquivalent zu istif ... then ... else ...
. Keine Sorge, dies ist eine häufige Gefahr .... && ... || ...
ist ein vollkommen gültiges Muster und eine gängige Bash-Sprache. Die Verwendung setzt Vorkenntnisse voraus (was gut zu beachten ist, wenn Anfänger im Publikum sind), aber OP hat die Haare, um zu beweisen, dass sie wissen, wie man offene Schachtabdeckungen vermeidet.Sie können auch Use Case / Esac verwenden
quelle
|
, vor dem trennen können)
. Diein
Anweisung entsprichtthen
inif
Anweisungen. Sie könnten argumentieren, dass es über eine Liste von Mustern funktioniert, wobei jede Liste ihre eigene Erklärung hat, was zu tun ist, wenn Sie aus Python stammen. Nicht wiesubstring in string
, sondernfor item in list
. Verwenden Sie a*
als letzte Anweisung, wenn Sie eineelse
Bedingung wünschen . Es kehrt bei der ersten Begegnung zurück.Das folgende Skript liest zeilenweise aus einer Datei mit dem Namen "testonthis" und vergleicht dann jede Zeile mit einer einfachen Zeichenfolge, einer Zeichenfolge mit Sonderzeichen und einem regulären Ausdruck. Wenn es nicht übereinstimmt, druckt das Skript die Zeile, andernfalls nicht.
Platz in Bash ist so wichtig. Also wird folgendes funktionieren:
Aber das wird nicht:
Verwenden Sie also bitte unverändert:
quelle
bash
sondern weil[
es sich tatsächlich um eine externe Binärdatei handelt (wie inwhich [
ergibt so etwas wie/usr/bin/[
)Ich würde wahrscheinlich Regexp-Übereinstimmungen verwenden, wenn die Eingabe nur wenige gültige Einträge enthält. ZB sind nur "Start" und "Stopp" gültige Aktionen.
Beachten Sie, dass ich die Variable
$ACTION
mit Doppelkommas in Kleinbuchstaben schreibe. Beachten Sie auch, dass dies bei zu alten Bash-Versionen nicht funktioniert.quelle
Bash 4+ Beispiele. Hinweis: Wenn Sie keine Anführungszeichen verwenden, treten Probleme auf, wenn Wörter Leerzeichen usw. enthalten. Zitieren Sie immer in Bash, IMO.
Hier sind einige Beispiele in Bash 4+:
Beispiel 1: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
Beispiel 2: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung wird nicht berücksichtigt):
Beispiel 3: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung beachten):
Beispiel 4: Überprüfen Sie die Zeichenfolge auf "Ja" (Groß- und Kleinschreibung beachten):
Beispiel 5, genaue Übereinstimmung (Groß- und Kleinschreibung beachten):
Beispiel 6, genaue Übereinstimmung (ohne Berücksichtigung der Groß- und Kleinschreibung):
Beispiel 7, genaue Übereinstimmung:
Genießen.
quelle
if [ "$a"="$b" ]
oder es funktioniert nicht ... kann keine Leerzeichen um das Gleiche habenIch habe es auf diese Weise gemacht, die mit Bash und Dash (sh) kompatibel ist :
quelle
(
Nichtverwendung?