Что печатает один восклицательный знак в Bash?

20

Bash использует восклицательные знаки для расширений истории, как объяснено в ответах на этот вопрос (например, sudo !!запускает предыдущую командную строку с помощью sudo). Тем не менее, я не могу найти нигде, который объясняет, что выполняет следующая команда (то есть один восклицательный знак):

!

Похоже, что ничего не печатать и выйти с 1, но я не уверен, почему это так. Я посмотрел онлайн и на странице руководства Bash, но ничего не могу найти, кроме того факта, что это «зарезервированное слово» - но так оно }и есть , и запускаю это:

}

печатает ошибку:

bash: syntax error near unexpected token `}'
мистифицировать
источник
1
Ничего такого. !указывает на «начало» выражения расширения истории.
Иордания

Ответы:

47

Одиночный !в начале команды отрицает состояние выхода команды или конвейера : если команда завершается 0, она переходит в состояние 1(сбой), а если она выходит из ненулевого значения, она превращается в 0(успешный) выход.

Это использование описано в руководстве по Bash:

Если зарезервированное слово «!» перед конвейером, состояние выхода - это логическое отрицание состояния выхода, как описано выше.

!С помощью следующей команды не отрицает пустую команду, которая ничего не делает и возвращает истинное (эквивалент в :команде ). Таким образом, он преобразует истину в ложь и выходит со статусом 1, но не выдает ошибки.


Существуют также и другие виды использования !внутри testи [[команд, где они отрицают условный тест. Это не связано с тем, что вы видите. И в вашем вопросе, и в тех случаях он не связан с расширением истории и !отделен от любых других терминов.

Майкл Гомер
источник
5
+1 за первый ответ, чтобы объяснить, что на самом деле выполняется и почему это объясняет код возврата.
Джефф Шаллер
11

Вы можете найти один восклицательный знак, документированный в разделе руководства bash. 3.2.2 Трубопроводы

Если зарезервированное слово «!» перед конвейером, состояние выхода - это логическое отрицание состояния выхода, как описано выше.

$ ! true; echo $?
1
$ ! false; echo $?
0

Также раздел 3.2.4.2 Условные конструкции

! выражение

Истинно, если выражение ложно.


Также раздел 4.1 Bourne Shell Builtins

! выраж

Истинно, если expr ложно.


Также следует отметить, что !начнется подстановка истории, если только не будет: пробел, табуляция, конец строки, '=' или '(' (когда опция оболочки extglob включена с помощью встроенной функции shopt).

Jesse_b
источник
0

Потому !что используется в сравнениях и означает НЕ .

Например:

a=3
b=2

[ $a -eq $b ] && echo "Equal"
[ ! $a -eq $b ] && echo "Not equal"
# of cause last comparison is possible to write as:
[ $a -eq $b ] || echo "Not equal"

[ $a -eq $b ]
echo $?
1
[ ! $a -eq $b ]
echo $?
0
Юрий Гончарук
источник
1
Это значение !аргумента testкоманды (включая встроенную версию bash), а не значение !при использовании в позиции команды.
Жиль "ТАК - перестань быть злым"
1
Это должно быть, ! [...]чтобы соответствовать вопросу в этом случае.
Майкл Гомер
Согласился с @Gilles и @Michael Homer. Я знал, что []это так test. Я немного поспешил.
Юрий Гончарук
-2

! встроенная команда, инвертирует смысл конвейера.

Другое использование:

#! встроенная команда, вызывает именованный интерпретатор для выполнения сценария.

! указатель события, помечает слово командной строки как подстановку истории

!= оператор неравенства

$! переменная оболочки, возвращает номер процесса последней фоновой команды.

Бхарат
источник
Просто для добавления можно использовать! $, Чтобы использовать последнее слово предыдущей команды, например так: ls -l /tmp cd !$ Это приведет вас в каталог / tmp.
Прыгающий кролик
-3

! сопровождаемый строкой выполняет самую последнюю предыдущую команду (все еще в буфере команд), которая началась с данной строки. Возможно, оболочка только что обнаружила, что ни одна предыдущая команда не начиналась с <null>.

pdelmonte
источник
3
Вы заметили, что в вопросе не было заданной строки ...?
Джефф Шаллер