Was bedeutet!

32

Ich folge einem Tutorial und es wird erwähnt, dass dieser Befehl ausgeführt werden soll:

sudo chmod 700 !$

Ich bin nicht vertraut mit !$. Was heißt das?

Andrew
quelle
5
Es ist im Allgemeinen sicher, echoetwas zu versuchen, wenn Sie nicht sicher sind, was es tun wird.
Shadur
8
@ Shadur, nicht immer. echo $(rm -rf /)
cjm
1
@cjm Sofern Sie nicht auf einem wirklich alten System arbeiten, benötigen Sie die entsprechende --no-preserve-rootOption. Wenn Sie in einem Programm die Wörter "no preserve" sehen, überlegen Sie sich besser genau, was es bewirkt.
wchargin
4
@WChargin Seien Sie sehr vorsichtig, wenn Sie davon ausgehen, dass "wirklich alt" und "nicht Linux / GNU-Coreutils nicht verwenden" dasselbe sind. sie sind nicht.
Chris Down

Antworten:

44

Grundsätzlich ist es das letzte Argument zum vorherigen Befehl.

!$ist das "Ende" des vorherigen Befehls. Betrachten Sie das folgende Beispiel: Wir beginnen mit der Suche nach einem Wort in einer Datei:

grep -i joe /some/long/directory/structure/user-lists/list-15

Wenn sich Joe in dieser Benutzerliste befindet, möchten wir ihn daraus entfernen. Wir können entweder vi mit diesem langen Verzeichnisbaum als Argument vi !$starten oder so einfach wie Which bash expand to:

vi /some/long/directory/structure/user-lists/list-15

( Quelle ; handliche Anleitung übrigens)


Es ist nichts wert, zwischen diesem !$Token und der speziellen Shell-Variablen zu unterscheiden $_. Tatsächlich werden beide zum letzten Argument des vorherigen Befehls erweitert. Wird !$jedoch während der Verlaufserweiterung erweitert , während $_sie während der Parametererweiterung erweitert wird . Eine wichtige Folge davon ist, dass !$der erweiterte Befehl bei Verwendung in Ihrem Verlauf gespeichert wird.

Betrachten Sie beispielsweise die Tastenanschläge

  • echo Foo Enter echo !$ Jar Enter Up Enter; und

  • echo Foo Enter echo $_ Jar Enter Up Enter.

(Die einzigen Zeichen, die geändert werden, sind das $!und $_in der Mitte.)

Wenn Sie im ersten Fall drücken Up, wird in der Befehlszeile Folgendes angezeigt echo Foo Jar: Die letzte in stdout geschriebene Zeile lautet Foo Jar.

Wenn Sie in letzterem Fall drücken Up, wird in der Befehlszeile Folgendes angezeigt echo $_ bar, jedoch $_mit einem anderen Wert als zuvor. In der Tat $_ist dies jetzt Jarder Fall, sodass die letzte in stdout geschriebene Zeile lautet Jar Jar.

Eine weitere Konsequenz ist, dass _bei anderen Parametererweiterungen beispielsweise die Befehlsfolge verwendet werden kann

printf '%s '    isomorphism
printf '%s\n'   ${_%morphism}sceles

druckt isomorphism isosceles. Aber es gibt keine " ${!$%morphism}" analoge Erweiterung.

Weitere Informationen zu den Expansionsphasen in Bash finden Sie im EXPANSIONAbschnitt von man 1 bash( in der Online-Ausgabe heißt dies Shell Expansions ). Der HISTORY EXPANSIONAbschnitt ist getrennt.

wchargin
quelle
6
Nett. Gut zu wissen. Gut, dass es Stack Exchange gibt. Es ist schwer, Google nach so etwas wie!$
Andrew
4
Übrigens können Sie in der Befehlszeile das letzte Argument des vorherigen Befehls einfügen insert-last-argument, normalerweise gebunden an M-..
Choroba
1
@ Andrew Bitte denken Sie daran, dies zu akzeptieren, wenn es Ihre Frage beantwortet. Akzeptieren und Upvoten anstatt Kommentare zu posten, ist die Art und Weise, in der sich das SE-Netzwerk bedankt. Hier finden Sie die "offizielle" Haltung.
Terdon
1
@ Andrew FYI, ich suchte bei Google nach "bash bang dollar" und bekam anständige Ergebnisse, einschließlich dieses Links als drittes Listing.
Wchargin
1
@terdon Ich habe letzte Nacht versucht, die Antwort zu akzeptieren, aber es war so schnell, dass ich warten musste, um sie zu akzeptieren.
Andrew
4

Genau genommen !$ist das letzte Wort des letzten Befehls aus der Verlaufsliste.

word - Eine Zeichenfolge, die von der Shell als Einheit behandelt wird. Wörter dürfen keine nicht in Anführungszeichen gesetzten Metazeichen enthalten.

Metazeichen - Ein Zeichen, das Wörter trennt, wenn es nicht in Anführungszeichen gesetzt wird. Ein Metazeichen ist ein Leerzeichen oder eines der folgenden Zeichen: '|', '&', ';', '(', ')', '<' oder '>'

leer - Ein Leerzeichen oder ein Tabulatorzeichen.

Beispiele:

set -o history # enable command history
set -o histexpand # enable ! style history substitution

HISTSIZE=10

# save all lines on the history list    
HISTCONTROL=
HISTIGNORE=

date
echo !$ # prints date

date>/dev/null
echo !$ # prints /dev/null

echo a b c>/dev/null
echo !$ # prints /dev/null

HISTCONTROL=ignorespace # lines which begin with a space character are not saved in the history list
echo a b c
 echo d e f # space at the beginning
echo !$ # prints c
Evgeny Vereshchagin
quelle
-3

!$ Gibt Ihnen den letzten Befehl, der für diesen bestimmten Benutzer verwendet wurde.

Sie können den Verlauf der zuvor verwendeten Befehle auch mit historycommand ermitteln ... probieren Sie es aus ....

HINWEIS: Für einen bestimmten Benutzer werden alle zuvor verwendeten Befehle in der Bash-Verlaufsdatei gespeichert.

Karthik G
quelle
1
Die anderen Antworten sind richtig. Dieser ist falsch.
Scott