Co znaczy! $?

32

Wykonuję samouczek, w którym wspomniano o uruchomieniu tego polecenia:

sudo chmod 700 !$

Nie jestem zaznajomiony z !$. Co to znaczy?

Andrzej
źródło
5
Na ogół można spróbować echoczegoś, jeśli nie jesteś pewien, co to zrobi.
Shadur
8
@Shadur, nie zawsze. echo $(rm -rf /)
cjm
1
@cjm O ile nie masz naprawdę starego systemu, będziesz potrzebować odpowiedniej --no-preserve-rootopcji, a jeśli zobaczysz w programie słowa „nie zachowuj”, lepiej dokładnie się zastanów.
wchargin
4
@WChargin Bądź bardzo ostrożny, zakładając, że „naprawdę stary” i „nie Linux / niestosowanie jądra GNU” to to samo; nie są.
Chris Down

Odpowiedzi:

44

Zasadniczo jest to ostatni argument do poprzedniego polecenia.

!$jest „końcem” poprzedniego polecenia. Rozważ następujący przykład: Zaczynamy od szukania słowa w pliku:

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

jeśli Joe jest na tej liście użytkowników, chcemy go z niego usunąć. Możemy wystrzelić vi z tym długim drzewem katalogów jako argumentem lub tak prosto, jak vi !$Rozwijanie bash do:

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

( Źródło ; poręczny przewodnik, przy okazji)


Nie warto nic odróżniać od tego !$tokena od specjalnej zmiennej powłoki $_. Rzeczywiście, oba rozwijają się do ostatniego argumentu poprzedniego polecenia. Jednak !$jest rozszerzany podczas rozszerzania historii , natomiast $_jest rozszerzany podczas rozszerzania parametrów . Jedną z ważnych konsekwencji tego jest to, że kiedy używasz !$, rozszerzone polecenie jest zapisywane w twojej historii.

Weźmy na przykład naciśnięcia klawiszy

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

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

(Jedyne zmienione znaki to $!i $_na środku.)

W pierwszym przypadku, gdy naciśniesz Up, wiersz poleceń czyta echo Foo Jar, więc ostatni wiersz zapisany na stdout to Foo Jar.

W drugim przypadku, gdy naciśniesz Up, linia poleceń czyta echo $_ bar, ale teraz $_ma inną wartość niż poprzednio - rzeczywiście $_jest teraz Jar, więc ostatni wiersz zapisany na stdout to Jar Jar.

Inną konsekwencją jest to, że _można go użyć w innych rozszerzeniach parametrów, na przykład w sekwencji poleceń

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

odbitki isomorphism isosceles. Ale nie ma analogicznego ${!$%morphism}rozszerzenia.

Aby uzyskać więcej informacji na temat faz ekspansji w Bash, zobacz EXPANSIONsekcję man 1 bash(nazywa się to Shell Expansions w wydaniu online). HISTORY EXPANSIONSekcji jest oddzielona.

wchargin
źródło
6
Miły. Dobrze wiedzieć. Dobrze, że jest wymiana stosów. Trudno jest wyszukać w Google coś takiego!$
Andrew
4
BTW, w wierszu polecenia możesz wstawić ostatni argument poprzedniego polecenia insert-last-argument, zwykle związany z M-..
choroba
1
@Andrew, pamiętaj, aby zaakceptować to, jeśli odpowie na twoje pytanie. Akceptowanie i ocenianie zamiast zamieszczania komentarzy to sposób wyrażania podziękowań w sieci SE, zobacz tutaj „oficjalne” stanowisko.
terdon
1
@Andrew FYI, szukałem w Google hasła „bash bang dollar” i uzyskałem przyzwoite wyniki, w tym ten link jako trzeci wpis.
wchargin
1
@terdon Próbowałem zaakceptować odpowiedź zeszłej nocy, ale było tak szybko, że musiałem czekać na jej przyjęcie.
Andrew
4

Ściśle mówiąc, !$jest to ostatnie słowo ostatniego polecenia z listy historii.

słowo - ciąg znaków traktowany przez powłokę jako jednostka. Słowa nie mogą zawierać niecytowanych metaznaków.

metaznak - znak, który, gdy nie jest cytowany, oddziela słowa. Metaznak jest pustym znakiem lub jednym z następujących znaków: „|”, „&”, „;”, „(”, „)”, „<” lub „>”

puste - spacja lub znak tabulacji.

Przykłady:

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
źródło
-3

!$ poda ostatnie polecenie użyte dla tego konkretnego użytkownika ....

możesz także znaleźć historię poleceń używanych wcześniej za pomocą historypolecenia ... wypróbuj ...

UWAGA: W przypadku konkretnego użytkownika wszystkie wcześniej użyte polecenia zostaną zapisane w pliku historii bash.

karthik G.
źródło
1
Pozostałe odpowiedzi są prawidłowe. Ten jest zły.
Scott,