Понимание восклицательного знака (!) В bash

108

я использовал

history | less

чтобы получить строки предыдущих команд и из чисел на левой стороне, я нашел строку, которую я хотел повторить (например, 22) и сделал

!22

в командной строке, и это сработало - выполнение набора команд на линии, которую я делал в то время. Я не могу понять, где используется восклицательный знак, что он представляет с точки зрения действий, предпринятых bash, и где его использовать. Из документации я не вижу объяснения, которое является «материальным».

Васса
источник
6
Этот ответ может помочь
Михаил Мрозек
9
Не ответ на ваш вопрос, но <ctrl> + R позволит вам интерактивно искать вашу историю и затем сразу же выполнить, если вы найдете то, что искали.
Кастерма

Ответы:

144

!это функция, которая первоначально появилась в оболочке C , еще в те дни, когда можно было рассчитывать, что на терминалах есть клавиши со стрелками. Это особенно полезно, если вы добавляете текущий номер команды в приглашение ( PS1="\!$ "), чтобы вы могли быстро просмотреть свой экран, чтобы получить номера для прошлых команд.

Теперь, когда вы можете использовать клавиши со стрелками и тому подобное Ctrl-Rдля поиска в истории команд, я не вижу особой пользы для этой функции.

Один из вариантов, который вы все еще можете найти полезным, - !!это повторное выполнение предыдущей команды. Сам по себе я не нахожу !!Enterничего быстрее, чем просто Enter, но это может быть полезно, когда объединено в большую команду.

Пример. Распространенная ошибка пилот-сигнала в sudoоснованных системах - забыть sudoпрефикс команды, требующей дополнительных привилегий. Новичок перепечатывает всю команду. Прилежный ученик редактирует команду из истории команд оболочки. Просветленный один из типов sudo !!.

Bash позволяет отключить !обработку в оболочке с помощью set +o histexpandили set +H. Вы можете отключить его в Zsh с помощью set -K.

Уоррен Янг
источник
4
Я считаю Ctrl-P Ctrl-J довольно быстрым; быстрее, чем Up Enter, по крайней мере.
2010 года
24
Если вы просто хотите выполнить последнюю команду, Up / Enter - это хорошо, но если вы хотите добавить к ней каким-либо образом (скажем, вы забыли sudoили что-то еще), то вы можете это сделать sudo !!, например. Это может быть немного быстрее, чем «Up / Ctrl-A (или Home, если вам повезет) / sudo / space / enter». YMMV. :)
1
@ AquariusPower: Просто процитируй это. Либо echo 'Hi!'или, echo "Hi!"либо echo Hi\!. Все делают одно и то же.
Уоррен Янг
1
setopt NO_BANG_HISTв Zsh может быть более запоминающимся, чем -K.
Грегори
48

Если здесь нет более длинного ответа, то, конечно, есть один, посвященный Super User, поскольку я недавно его прочитал. На странице руководства bash вы можете найти огромный раздел, озаглавленный РАСШИРЕНИЕ ИСТОРИИ .

Вы можете сделать целый хост больше, чем просто запустить последнюю команду или команду номер X. Вы можете сделать что-то вроде !catзапуска последней команды, которая началась с cat. Или !?bash?:s/bash/csh/запускает последнюю содержащую команду, bashно заменяет ее на csh.

Плачь Хавок
источник
3
Хотя это и не является прямым ответом на вопрос ОП, это требует гораздо большего числа голосов. Так полезно! Спасибо, Хавок.
Malvim
Мне действительно нужно заглянуть в справочную страницу, прежде чем я начну гуглить.
erikbwork
1
!!:s/bash/csh/фактически запускает последнюю команду , а затем заменяет bash на csh, если он присутствует. Не последняя команда, включающая bash. Это было бы !?bash?:s/bash/csh/или , может быть!?bash?:s/%/csh/
CDE
В течение нескольких лет интенсивно используя Bash, я был шокирован, обнаружив, что никогда раньше не знал об этом ключевом слове, и хотя я часами просматривал manстраницы, эта функция невероятно неясна. Спасибо за указание на соответствующий раздел - это единственное место в реальных документах, где они достаточно подробно объясняют это.
Стив Беннер
39

Многое можно сделать с !такими как:

  • выполнить команду, набранную до 3 команд: !-3
  • выполнить команду, которая начинается с !ls

и многое другое. Смотрите 15 примеров расширения Linux Bash History, которые вы должны знать

user379997
источник
Проголосовал за это. Ни у одного из других ответов не было ни одной из этих хитрых уловок.
Гергели Лукачи
Проголосовал, потому что www.thegeekstuff.com - просто фантастический ресурс, и это была одна из немногих статей о Linux, которых я раньше не видел. Очень полезно.
Стив Беннер
4

Мой друг написал мне по электронной почте это:

Это часть библиотеки истории GNU. В bash он используется для повторного запуска команд в вашей истории. Если вы хотите быть хардкорным, grep для history_expansion_char в bash-4.1 / lib / readline / histexpand.c для подробностей реализации.

Васса
источник
3

Конечно, вы можете сделать, !!чтобы повторно использовать последнюю команду в оболочке bash. И затем есть !$повторно использовать последнюю часть вашей последней команды.

например, посмотреть какой-нибудь файл

less path/to/your/file.txt

Если вы теперь хотите редактировать тот же файл, вы можете использовать, !$чтобы получить только путь к файлу из последней команды

vim !$
Тешан Шанука Дж
источник
1
Ах, я надеялся найти это. Как это ведет себя с двумя аргументами?
Джонатан
Это просто будет использовать последний аргумент из двух. $touch f1 f2и затем $vim !$будет оценивать с$vim f2
Teshan Shanuka J