Что значит! $?

32

Я просматриваю учебник, в котором упоминается о запуске этой команды:

sudo chmod 700 !$

Я не знаком с !$. Что это означает?

Эндрю
источник
5
Обычно безопасно пытаться echoчто-то сделать, если вы не уверены, что это будет делать.
Шадур
8
@ Шадур, не всегда. echo $(rm -rf /)
cjm
1
@cjm Если вы не используете действительно старую систему, вам понадобится такая --no-preserve-rootопция, и если в программе вы увидите слова «нет сохранения», вам лучше по-настоящему тщательно подумать о том, что она делает.
wchargin
4
@WChargin Будьте очень осторожны, предполагая, что «действительно старый» и «не Linux / не использующий GNU coreutils» - это одно и то же; они не.
Крис Даун

Ответы:

44

По сути, это последний аргумент предыдущей команды.

!$это «конец» предыдущей команды. Рассмотрим следующий пример. Начнем с поиска слова в файле:

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

Если Джо в этом списке пользователей, мы хотим удалить его из него. Мы можем либо запустить vi с этим длинным деревом каталогов в качестве аргумента, либо так же просто, как vi !$расширение bash:

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

( источник ; кстати, удобный справочник)


Ничего не стоит разграничивать этот !$токен и специальную переменную оболочки $_. Действительно, оба расширяются до последнего аргумента предыдущей команды. Однако !$расширяется при расширении истории , а $_расширяется при расширении параметров . Одним из важных следствий этого является то, что при использовании !$, то расширенная команда сохраняется в истории.

Например, рассмотрим нажатия клавиш

  • echo Foo Enter echo !$ Jar Enter Up Enter; а также

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

(Изменены только символы $!и $_в середине.)

В первом случае, когда вы нажимаете Up, командная строка читает echo Foo Jar, поэтому последняя строка записывается в stdout Foo Jar.

В последнем случае, когда вы нажимаете Up, командная строка читает echo $_ bar, но теперь $_имеет значение, отличное от того, что было раньше - на самом деле, $_сейчас Jar, поэтому последняя строка, записанная в stdout - это Jar Jar.

Другим следствием является то, что _могут использоваться другие расширения параметров, например, последовательность команд

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

отпечатки isomorphism isosceles. Но нет аналогичного " ${!$%morphism}" расширения.

Для получения дополнительной информации о фазах расширения в Bash см. EXPANSIONРаздел man 1 bash(это называется Shell Expansions в онлайн-издании). HISTORY EXPANSIONРаздел отдельно.

wchargin
источник
6
Ницца. Хорошо знать. Кроме того, хорошо, что есть стек обмена. Трудно искать в Google что-то вроде!$
Эндрю
4
Кстати, в командной строке вы можете вставить последний аргумент предыдущей команды insert-last-argument, обычно с привязкой к M-..
Чороба
1
@ Андрей, пожалуйста, не забудьте принять это, если он отвечает на ваш вопрос. Принятие и голосование, а не публикация комментариев - вот как выражается благодарность в сети SE, см. Здесь «официальную» позицию.
Тердон
1
@ Андрей FYI, я искал в Google «bash bang dollar» и получил приличные результаты, включая эту ссылку в качестве третьего списка.
wchargin
1
@terdon Я пытался принять ответ прошлой ночью, но это было так быстро, что я был вынужден ждать, чтобы принять его.
Андрей
4

Строго говоря, !$это последнее слово последней команды из списка истории.

слово - последовательность символов, рассматриваемая оболочкой как единое целое. Слова не могут содержать метасимволы без кавычек.

метасимвол - символ, который без кавычек разделяет слова. Метасимвол - это пробел или один из следующих символов: '|', '&', ';', '(', ')', '<' или '>'

пусто - пробел или символ табуляции.

Примеры:

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
Евгений Верещагин
источник
-3

!$ даст вам последнюю команду, использованную для этого конкретного пользователя ....

Вы также можете найти историю команд, использованных ранее, используя historyкоманду ... попробуйте ...

ПРИМЕЧАНИЕ. Для конкретного пользователя все ранее использованные команды будут сохранены в файле истории bash.

Картик G
источник
1
Другие ответы верны. Это неправильно.
Скотт