Warum wird echo {1,2,3}auf 1 2 3 erweitert, was ein erwartetes Verhalten ist, während echo [[:digit:]]zurückgegeben wird, [[:digit:]]während ich erwartet habe, dass alle Ziffern von 0bis gedruckt werden 9?
Weil es zwei verschiedene Dinge sind. Dies {1,2,3}ist ein Beispiel für die Erweiterung der Zahnspange . Das {1,2,3}Konstrukt wird von der Shell erweitert , bevor es echoüberhaupt angezeigt wird. Sie können sehen, was passiert, wenn Sie Folgendes verwenden set -x:
$ set-x
$ echo {1,2,3}+ echo 123123
Wie Sie sehen können, wird der Befehl echo {1,2,3}erweitert auf:
echo 123
Ist [[:digit:]]jedoch eine POSIX-Zeichenklasse . Wenn Sie es geben echo, verarbeitet die Shell es auch zuerst, aber dieses Mal wird es als Shell-Glob verarbeitet . Es funktioniert genauso, als ob Sie ausführen, echo *wodurch alle Dateien im aktuellen Verzeichnis gedruckt werden. [[:digit:]]Ist aber ein Shell Glob, der mit jeder Ziffer übereinstimmt. Wenn ein Shell-Glob in Bash mit nichts übereinstimmt, wird er auf sich selbst erweitert:
Wenn der Globus mit etwas übereinstimmt, wird dieser gedruckt:
$ echo /e*c
+ echo /etc
/etc
In beiden Fällen wird echonur gedruckt, was die Shell zum Drucken auffordert. Im zweiten Fall wird jedoch angegeben, dass der Globus gedruckt werden soll, da der Glob mit etwas übereinstimmt ( /etc).
Da Sie also keine Dateien oder Verzeichnisse haben, deren Name aus genau einer Ziffer besteht (was [[:digit:]]übereinstimmen würde), wird der Glob auf sich selbst erweitert und Sie erhalten:
$ echo [[:digit:]][[:digit:]]
Versuchen Sie nun, eine Datei mit dem Namen zu erstellen 5und denselben Befehl auszuführen:
$ echo [[:digit:]]5
Und wenn es mehr als eine übereinstimmende Datei gibt:
$ touch 15
$ echo [[:digit:]]15
Dies ist (irgendwie) man bashin der Erläuterung der nullglobOptionen dokumentiert , die dieses Verhalten ausschalten:
nullglob
Ifset, bash allows patterns which match no files (see
PathnameExpansion above) to expand to a null string,
rather than themselves.
Siehe auch shopt -s failglob, um ein nützlicheres Verhalten zu erhalten, das dem von modernen Muscheln wie zshoder ähnelt fish.
Stéphane Chazelas
Ich stimme Stéphane zu failglob. nullglobkann zu unerwarteten Problemen führen, z. B. beim Einfügen einer URL mit einer ?.
Kevin
1
Klar, ich habe nur erwähnt nullglob, um zu demonstrieren, dass das Muster von der Shell als Glob interpretiert wird.
Terdon
14
{1,2,3}ist Klammernerweiterung , dehnt es sich auf die Worte , ohne Rücksicht aufgeführt ihre Bedeutung.
[...]ist eine Zeichengruppe, die in der Dateinamenerweiterung (oder im Platzhalter oder Glob) ähnlich wie das Sternchen *und das Fragezeichen verwendet wird ?. Es entspricht jedem einzelnen darin aufgelisteten Zeichen oder Zeichen, die Mitglieder benannter Gruppen sind, z. B. [:digit:]wenn diese aufgelistet sind. Das Standardverhalten der meisten Shells besteht darin, den Platzhalter unverändert zu lassen, wenn keine passenden Dateien vorhanden sind.
(Beachten Sie, dass Sie einen Platzhalter / ein Muster nicht wirklich in eine Reihe von Zeichenfolgen umwandeln können, mit denen es übereinstimmen würde. Das Sternchen kann mit einer beliebigen Zeichenfolge beliebiger Länge übereinstimmen. Wenn Sie also ein beliebiges Muster erweitern, das es enthält, wird eine unendliche Liste von Zeichenfolgen erstellt.)
So:
$ bash -c 'echo [[:digit:]]'# bash leaves it as-is[[:digit:]]
$ zsh -c 'echo [[:digit:]]'# zsh by default complains if no match
zsh:1: no matches found:[[:digit:]]
$ touch 13 d i g t
$ bash -c 'echo [[:digit:]]'# now there are two matches13# note that d, i, g and t do NOT match
Aber dennoch:
$ bash -c 'echo {1,2,3}'123
Beide werden durch die Shell erweitert . Es spielt keine Rolle, ob der von Ihnen ausgeführte Befehl lsoder echooder ist rm. Beachten Sie auch, dass wenn eines dieser Elemente zitiert wird, es nicht erweitert wird:
$ bash -c 'echo "[[:digit:]]"'# even though matching files still exist[[:digit:]]
$ bash -c 'echo "{1,2,3}"'{1,2,3}
danke für deine antwort, bin neu in linux, also lass mich dich bitte fragen, wie echo mit dateien 1 3 zusammenhängt. es ist die funktion, seine argumente zu drucken, um nicht nach
dateien zu
1
@AbdAllahTalaat das hat eigentlich nichts mit echo zu tun. Die Shell (z. B. Bash) "erweitert" sich [[:digit:]]vor dem Weitergeben an echo, echosieht also nie [[:digit:]], sie sieht nur 1 3. Sie können dies in Aktion sehen, indem Sie set -xausführen, wodurch die tatsächlich ausgeführten Befehle gedruckt werden (ausführen set +x, um sie wieder auszuschalten).
Terdon
@AbdAllahTalaat, echosucht nicht nach Dateien, die Shell tut dies, bevor das ausgeführt wird echo.
Ilkkachu
Zumal ich denke, dass unter DOS / Windows die Dienstprogramme die Platzhalter erweitern, nicht die Shell. (Ich kann mich irren)
ilkkachu
Tut mir leid, Leute, ich habe die richtige Antwort auf Tedrons Antwort verschoben, weil sein Kommentar die Bedeutung enthielt, dass Bash das ist, was die Arbeit nicht wiedergibt. Auch seine Antwort enthielt diese Bedeutung. Sie alle haben mir geholfen. Ich wünschte, ich könnte es sagen richtige Antwort für alle Ihre Antworten und Kommentare
AbdAllah Talaat
4
{1,2,3}(und zB {1..3}sind Verstrebung Expansionen . Sie werden von der Schale , bevor die Befehlsausführung interpretiert.
[[:digit:]]ist ein Mustervergleichstoken , aber Sie verwenden es nicht an einem Speicherort mit Dateien, die diesem Muster entsprechen. Wenn Sie eine Musterübereinstimmung verwenden, die keine Übereinstimmungen aufweist, wird sie auf sich selbst erweitert:
Antworten:
Weil es zwei verschiedene Dinge sind. Dies
{1,2,3}
ist ein Beispiel für die Erweiterung der Zahnspange . Das{1,2,3}
Konstrukt wird von der Shell erweitert , bevor esecho
überhaupt angezeigt wird. Sie können sehen, was passiert, wenn Sie Folgendes verwendenset -x
:Wie Sie sehen können, wird der Befehl
echo {1,2,3}
erweitert auf:Ist
[[:digit:]]
jedoch eine POSIX-Zeichenklasse . Wenn Sie es gebenecho
, verarbeitet die Shell es auch zuerst, aber dieses Mal wird es als Shell-Glob verarbeitet . Es funktioniert genauso, als ob Sie ausführen,echo *
wodurch alle Dateien im aktuellen Verzeichnis gedruckt werden.[[:digit:]]
Ist aber ein Shell Glob, der mit jeder Ziffer übereinstimmt. Wenn ein Shell-Glob in Bash mit nichts übereinstimmt, wird er auf sich selbst erweitert:Wenn der Globus mit etwas übereinstimmt, wird dieser gedruckt:
In beiden Fällen wird
echo
nur gedruckt, was die Shell zum Drucken auffordert. Im zweiten Fall wird jedoch angegeben, dass der Globus gedruckt werden soll, da der Glob mit etwas übereinstimmt (/etc
).Da Sie also keine Dateien oder Verzeichnisse haben, deren Name aus genau einer Ziffer besteht (was
[[:digit:]]
übereinstimmen würde), wird der Glob auf sich selbst erweitert und Sie erhalten:Versuchen Sie nun, eine Datei mit dem Namen zu erstellen
5
und denselben Befehl auszuführen:Und wenn es mehr als eine übereinstimmende Datei gibt:
Dies ist (irgendwie)
man bash
in der Erläuterung dernullglob
Optionen dokumentiert , die dieses Verhalten ausschalten:Wenn Sie diese Option einstellen:
quelle
shopt -s failglob
, um ein nützlicheres Verhalten zu erhalten, das dem von modernen Muscheln wiezsh
oder ähneltfish
.failglob
.nullglob
kann zu unerwarteten Problemen führen, z. B. beim Einfügen einer URL mit einer?
.nullglob
, um zu demonstrieren, dass das Muster von der Shell als Glob interpretiert wird.{1,2,3}
ist Klammernerweiterung , dehnt es sich auf die Worte , ohne Rücksicht aufgeführt ihre Bedeutung.[...]
ist eine Zeichengruppe, die in der Dateinamenerweiterung (oder im Platzhalter oder Glob) ähnlich wie das Sternchen*
und das Fragezeichen verwendet wird?
. Es entspricht jedem einzelnen darin aufgelisteten Zeichen oder Zeichen, die Mitglieder benannter Gruppen sind, z. B.[:digit:]
wenn diese aufgelistet sind. Das Standardverhalten der meisten Shells besteht darin, den Platzhalter unverändert zu lassen, wenn keine passenden Dateien vorhanden sind.(Beachten Sie, dass Sie einen Platzhalter / ein Muster nicht wirklich in eine Reihe von Zeichenfolgen umwandeln können, mit denen es übereinstimmen würde. Das Sternchen kann mit einer beliebigen Zeichenfolge beliebiger Länge übereinstimmen. Wenn Sie also ein beliebiges Muster erweitern, das es enthält, wird eine unendliche Liste von Zeichenfolgen erstellt.)
So:
Aber dennoch:
Beide werden durch die Shell erweitert . Es spielt keine Rolle, ob der von Ihnen ausgeführte Befehl
ls
oderecho
oder istrm
. Beachten Sie auch, dass wenn eines dieser Elemente zitiert wird, es nicht erweitert wird:quelle
[[:digit:]]
vor dem Weitergeben anecho
,echo
sieht also nie[[:digit:]]
, sie sieht nur1 3
. Sie können dies in Aktion sehen, indem Sieset -x
ausführen, wodurch die tatsächlich ausgeführten Befehle gedruckt werden (ausführenset +x
, um sie wieder auszuschalten).echo
sucht nicht nach Dateien, die Shell tut dies, bevor das ausgeführt wirdecho
.{1,2,3}
(und zB{1..3}
sind Verstrebung Expansionen . Sie werden von der Schale , bevor die Befehlsausführung interpretiert.[[:digit:]]
ist ein Mustervergleichstoken , aber Sie verwenden es nicht an einem Speicherort mit Dateien, die diesem Muster entsprechen. Wenn Sie eine Musterübereinstimmung verwenden, die keine Übereinstimmungen aufweist, wird sie auf sich selbst erweitert:quelle