¿Qué hace escribir un solo signo de exclamación en Bash?

20

Bash usa signos de exclamación para las expansiones del historial, como se explica en las respuestas a esta pregunta (por ejemplo, sudo !!ejecuta la línea de comandos anterior con sudo). Sin embargo, no puedo encontrar ningún lugar que explique lo que hace el siguiente comando (es decir, un solo signo de exclamación):

!

Parece que no imprime nada y sale con 1, pero no estoy seguro de por qué lo hace. He buscado en línea y en la página de manual de Bash, pero no puedo encontrar nada, aparte del hecho de que es una "palabra reservada", pero así es }, y ejecuto esto:

}

imprime un error:

bash: syntax error near unexpected token `}'
Josh
fuente
1
Nada. !indica el "inicio" de una expresión de expansión de historial.
jordanm

Respuestas:

47

El solitario !al comienzo de un comando niega el estado de salida del comando o la tubería : si el comando sale 0, se convertirá en 1(falla), y si sale de un estado distinto de cero, lo convertirá en una 0salida (exitosa).

Este uso está documentado en el manual de Bash:

Si la palabra reservada '!' precede a la tubería, el estado de salida es la negación lógica del estado de salida como se describe anteriormente.

Un !sin siguiente comando niega el comando vacío, que no hace nada y devuelve true (equivalente a la :orden ). Por lo tanto, invierte el verdadero en falso y sale con el estado 1, pero no produce ningún error.


También hay otros usos de !los comandos testy [[, donde niegan una prueba condicional. Estos no están relacionados con lo que estás viendo. Tanto en su pregunta como en esos casos no está relacionada con la expansión del historial y !está separada de cualquier otro término.

Michael Homer
fuente
55
+1 para la primera respuesta para explicar qué se ejecuta realmente y por qué eso explica el código de retorno.
Jeff Schaller
11

Puede encontrar el signo de exclamación único documentado en el manual de bash sección 3.2.2 Tuberías

Si la palabra reservada '!' precede a la tubería, el estado de salida es la negación lógica del estado de salida como se describe anteriormente.

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

También la sección 3.2.4.2 Construcciones condicionales

! expresión

Verdadero si la expresión es falsa.


También la sección 4.1 Bourne Shell Builtins

! expr

Es cierto si expr es falso.


También debe tenerse en cuenta que !comenzará la sustitución del historial a menos que vaya seguido de: un espacio, una pestaña, el final de la línea, '=' o '(' (cuando la opción de shell extglob está habilitada usando el shopt incorporado).

Jesse_b
fuente
0

Porque !se usa en comparaciones y significa NO .

Por ejemplo:

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
Yurij Goncharuk
fuente
1
Ese es el significado de !un argumento para el testcomando (incluida la versión incorporada de bash), no el significado de !cuando se usa en la posición del comando.
Gilles 'SO- deja de ser malvado'
1
Tendría que ser ! [...]para que coincida con la pregunta en este caso.
Michael Homer
De acuerdo con @Gilles y @Michael Homer. Sabía que []es así test. Estoy un poco apurado.
Yurij Goncharuk
-2

! comando incorporado, invierte el sentido de una tubería.

Otros usos:

#! comando incorporado, invoca al intérprete nombrado para ejecutar el script.

! designador de evento, marca una palabra de línea de comando como una sustitución del historial

!= operador de desigualdad

$! variable de shell, devuelve el número de proceso del último comando en segundo plano.

Bharat
fuente
Solo para agregar, uno puede usar! $ Para usar la última palabra del comando anterior de la siguiente manera: ls -l /tmp cd !$ Esto lo llevará al directorio / tmp.
Hopping Bunny
-3

! seguido de una cadena ejecuta el comando anterior más reciente (todavía en el búfer de comandos) que comenzó con la cadena dada. Quizás el shell descubrió que ningún comando anterior comenzó con <null>.

pdelmonte
fuente
3
¿Notaste que no había una cadena dada en la pregunta ...?
Jeff Schaller