Ich möchte überprüfen, ob eine Zeichenfolge mit "node" beginnt, z. B. "node001". Etwas wie
if [ $HOST == user* ]
then
echo yes
fi
Wie kann ich das richtig machen?
Ich muss außerdem Ausdrücke kombinieren, um zu überprüfen, ob HOST entweder "user1" ist oder mit "node" beginnt.
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Wie kann ich das richtig machen?
string
bash
comparison
Tim
quelle
quelle
Antworten:
In diesem Snippet im Advanced Bash Scripting Guide heißt es:
Sie hatten es also fast richtig; Sie brauchten doppelte Klammern, keine einfachen Klammern.
In Bezug auf Ihre zweite Frage können Sie sie folgendermaßen schreiben:
Welches wird widerhallen
Bashs
if
Syntax ist schwer zu gewöhnen (IMO).quelle
[[ $a == z* ]]
und[[ $a == "z*" ]]
? Mit anderen Worten: Arbeiten sie anders? Und was genau meinst du, wenn du sagst "$ a ist gleich z *"?[[ $a == *com ]]
Wenn Sie eine neuere Version von Bash (v3 +) verwenden, empfehle ich beispielsweise den Bash-Regex-Vergleichsoperator
=~
.this or that
Verwenden Sie|
zum Beispiel " Regex", um eine Übereinstimmung zu erzielenHinweis - Dies ist die richtige Syntax für reguläre Ausdrücke.
user*
bedeutetuse
und null oder mehr Vorkommen vonr
, souse
unduserrrr
werden übereinstimmen.user.*
Mitteluser
und Null-oder-mehr beliebigen Zeichen, souser1
,userX
werden entsprechen.^user.*
bedeutet, dass das Musteruser.*
am Anfang von $ HOST übereinstimmt .Wenn Sie mit der Syntax regulärer Ausdrücke nicht vertraut sind, verweisen Sie auf diese Ressource .
quelle
=~
Ihrer Information, der Bash- Operator führt nur dann einen Abgleich regulärer Ausdrücke durch, wenn die rechte Seite UNQUOTED ist. Wenn Sie die rechte Seite zitieren "Jeder Teil des Musters kann zitiert werden, um zu erzwingen, dass es als Zeichenfolge abgeglichen wird." (1.) Stellen Sie sicher, dass die regulären Ausdrücke immer ohne Anführungszeichen rechts stehen. (2.) Wenn Sie Ihren regulären Ausdruck in einer Variablen speichern, stellen Sie sicher, dass Sie bei der Parametererweiterung NICHT die rechte Seite in Anführungszeichen setzen.Ich versuche immer, bei POSIX zu bleiben,
sh
anstatt Bash-Erweiterungen zu verwenden, da einer der Hauptpunkte der Skripterstellung die Portabilität ist (neben dem Verbinden von Programmen, nicht deren Ersetzen).Im
sh
gibt es eine einfache Möglichkeit, nach einer "is-prefix" -Bedingung zu suchen.In Anbetracht dessen, wie alt, arkan und crufty sh ist (und Bash ist nicht das Heilmittel: Es ist komplizierter, weniger konsistent und weniger portabel), möchte ich auf einen sehr schönen funktionalen Aspekt hinweisen: Während einige Syntaxelemente wie
case
eingebaut sind Die resultierenden Konstrukte unterscheiden sich nicht von anderen Jobs. Sie können auf die gleiche Weise zusammengesetzt werden:Oder noch kürzer
Oder noch kürzer (nur um
!
als Sprachelement zu präsentieren - aber das ist jetzt ein schlechter Stil)Wenn Sie explizit sein möchten, erstellen Sie Ihr eigenes Sprachelement:
Ist das nicht eigentlich ganz nett?
Und seit
sh
es sich im Grunde nur um Jobs und String-Listen handelt (und um interne Prozesse, aus denen Jobs bestehen), können wir jetzt sogar eine leichte funktionale Programmierung durchführen:Das ist elegant. Nicht, dass ich die Verwendung
sh
für irgendetwas Ernstes befürworten würde - es bricht allzu schnell bei realen Anforderungen ab (keine Lambdas, daher müssen wir Zeichenfolgen verwenden. Verschachtelungsfunktionsaufrufe mit Zeichenfolgen sind jedoch nicht möglich, Pipes sind nicht möglich usw.)quelle
case $HOST in user01 | node* ) ...
if case $HOST in node*) true;; *) false;; esac; then
Ich habe es hier und da gesehen, für mein Auge sieht es irgendwie zerknittert aus.case
Befehle Befehle sind, können sie hineingehenif ... then
.beginswith() { case "$2" in "$1"*) true;; *) false;; esac; }
anders sein, wenn$1
es ein Literal gibt*
oder?
es eine falsche Antwort geben könnte.Sie können nur den Teil der Zeichenfolge auswählen, den Sie überprüfen möchten:
Für Ihre Folgefrage können Sie einen OP verwenden :
quelle
${HOST:0:4}
HOST='a b'; if [ ${HOST:0:4} = user ] ; then echo YES ; fi
Ich bevorzuge die anderen bereits veröffentlichten Methoden, aber einige Leute verwenden gerne:
Bearbeiten:
Ich habe Ihre Alternativen zu der obigen case-Anweisung hinzugefügt
In Ihrer bearbeiteten Version haben Sie zu viele Klammern. Es sollte so aussehen:
quelle
Während ich die meisten Antworten hier ganz richtig finde, enthalten viele von ihnen unnötige Bashismen. Die POSIX-Parametererweiterung bietet Ihnen alles, was Sie brauchen:
und
${var#expr}
Streifen die kleinste prefix Anpassungexpr
aus${var}
und kehrt das. Wenn${host}
also nicht mituser
(node
) beginnt , ist${host#user}
(${host#node}
) dasselbe wie${host}
.expr
erlaubtfnmatch()
Wildcards, also${host#node??}
und Freunde arbeiten auch.quelle
[[ $host == user* ]]
notwendig sein könnte, da er weitaus lesbarer ist als[ "${host#user}" != "${host}" ]
. Wenn Sie also die Umgebung steuern, in der das Skript ausgeführt wird (auf die neuesten Versionen vonbash
), ist die erstere vorzuziehen.has_prefix()
Funktion packen und es nie wieder anschauen.Da
#
Bash eine Bedeutung hat, bin ich zu folgender Lösung gekommen.Außerdem packe ich lieber Strings mit "", um Leerzeichen usw. zu überwinden.
quelle
blah:
, sieht so aus, als wäre dies die Antwort!Mark Rushakoffs Antwort mit dem höchsten Rang wird ein kleines bisschen mehr Syntaxdetails hinzugefügt.
Der Ausdruck
Kann auch geschrieben werden als
Der Effekt ist der gleiche. Stellen Sie einfach sicher, dass sich der Platzhalter außerhalb des angegebenen Textes befindet. Befindet sich der Platzhalter in Anführungszeichen, wird er wörtlich interpretiert (dh nicht als Platzhalter).
quelle
@OP, für beide Fragen können Sie case / esac verwenden:
Zweite Frage
Oder Bash 4.0
quelle
;&
nur in Bash> = 4 verfügbar ist.nicht funktioniert, weil alle
[
,[[
undtest
erkennen die gleiche nicht - rekursive Grammatik. Siehe Abschnitt BEDINGTE AUSDRÜCKE auf Ihrer Bash-Manpage.Nebenbei sagt der SUSv3
Sie müssten es so schreiben, aber der Test unterstützt es nicht:
Test verwendet = für die Zeichenfolgengleichheit und unterstützt vor allem keinen Mustervergleich.
case
Ichesac
habe eine gute Unterstützung für den Mustervergleich:Es hat den zusätzlichen Vorteil, dass es nicht von Bash abhängt und die Syntax portabel ist. Von der Single Unix Specification , The Shell Command Language :
quelle
[
undtest
sind Bash Builtins sowie externe Programme. Versuchen Sie estype -a [
.if [ -z $aa -or -z $bb ]
; ... gibt " bash: [: -or: binärer Operator erwartet "; geht jedochif [ -z "$aa" -o -z "$bb" ] ; ...
vorbei.grep
Dies ist POSIX und sieht besser aus als
case
Lösungen:Erläuterung:
printf '%s'
Um zu verhindernprintf
, dass Backslash-Escapezeichen erweitert werden: Bash printf wörtliche wörtliche Zeichenfolgegrep -q
Verhindert das Echo von Übereinstimmungen mit stdout: So überprüfen Sie mithilfe von Bash, ob eine Datei eine bestimmte Zeichenfolge enthältgrep -E
ermöglicht erweiterte reguläre Ausdrücke, die wir für die benötigen^
quelle
Ich habe die Antwort von @ markrushakoff optimiert, um sie zu einer aufrufbaren Funktion zu machen:
Verwenden Sie es so:
Hier ist eine komplexere Version, die einen angegebenen Standardwert vorsieht:
Verwenden Sie es so:
quelle
Eine andere Sache, die Sie tun können, ist
cat
herauszufinden, was Sie wiedergeben und mit was Sie pfeifeninline cut -c 1-1
quelle