Me doy cuenta de que !
tiene un significado especial en la línea de comandos en el contexto del historial de la línea de comandos, pero aparte de eso, en un script de ejecución, el signo de exclamación a veces puede causar un error de análisis.
Creo que tiene algo que ver con un event
, pero no tengo idea de qué es un evento o qué hace. Aun así, el mismo comando puede comportarse de manera diferente en diferentes situaciones.
El último ejemplo, a continuación, causa un error; pero ¿por qué, cuando el mismo código funcionó fuera de la sustitución del comando? .. utilizando GNU bash 4.1.5
# This works, with or without a space between ! and p
{ echo -e "foo\nbar" | sed -nre '/foo/! p'
echo -e "foo\nbar" | sed -nre '/foo/!p'; }
# bar
# bar
# This works, works when there is a space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
# bar
# This causes an ERROR, with NO space between ! and p
var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
# bash: !p': event not found
bash
command-history
quoting
Peter.O
fuente
fuente
protected
hubiera sido más apropiado. (protegido por 'comillas simples')var=$(…)
(sin comillas dobles), y funcionará como (creo) que espera. Esto sigue siendo “seguro” porque la parte del valor de una asignación simple no está sujeta a la división de palabras o comodines (aunque esto puede no ser cierto de las asignaciones hechas a través de órdenes internas (por ejemploexport
,local
, etc.) en todas las conchas). Desafortunadamente, esto no se extiende más allá de las tareas simples, ya que las comillas dobles son la forma de protegerse contra la división y el bloqueo de palabras mientras se obtienen otros tipos de expansión en otros contextos.Respuestas:
El
!
personaje invoca la sustitución de la historia de bash. Cuando lo sigue una cadena (como en su ejemplo de error) intenta expandirse al último evento del historial que comenzó con esa cadena. Al igual que$var
se expande al valor de esa cadena,!echo
se expandiría al último comando de eco en su historial.El espacio es un personaje rompedor en tales expansiones. Primero observe cómo funcionaría esto con las variables:
Lo mismo sucederá con la expansión de la historia. El carácter de explosión (
!
) comienza una secuencia de reemplazo del historial, pero solo si es seguido por una cadena. Seguirlo con un espacio lo convierte en una explosión literal en lugar de parte de una secuencia de reemplazo.Puede evitar este tipo de reemplazo para la expansión de variables e historial utilizando comillas simples. Sus primeros ejemplos utilizaron comillas simples y, por lo tanto, funcionaron bien. Sus últimos ejemplos están entre comillas dobles y, por lo tanto, bash los escaneó en busca de secuencias de expansión antes de hacer cualquier otra cosa. La única razón por la que el primero no se disparó es porque el espacio es un carácter de ruptura como se muestra arriba.
fuente
var=word; echo "test '$var'"; echo 'test "$var"'
Como ya dijo Caleb ,
!
se usa para invocar la sustitución de la historia de bash.Si, como yo, siente que no necesita dicha función, puede deshabilitarla insertando la siguiente línea en
~/.bashrc
:Yo no lo necesito porque la historia se puede recuperar mediante la flecha hacia arriba y Ctrl- rbúsqueda hacia atrás incrementales. Consulte la página del manual de bash, sección Comandos para manipular el historial para obtener una lista detallada de accesos directos.
fuente
!!
?set +H
en el script funciona igual de bien :) +1tu primer ejemplo:
podría reducirse a
Entre comillas simples, todos los caracteres conservan sus valores literales. Por lo tanto,
!
ha perdido su significado especial y la expansión de la historia no se realiza.su segundo y tercer ejemplo:
podría reducirse a
'! p'
y'!p'
son esencialmente partes de las cadenas entre comillas dobles.Entre comillas dobles, todos los personajes conservan sus valores literales Excepto
$
,`
,\
y!
.Eso implica las comillas simples de
'! p'
y'!p'
ha perdido sus significados especiales (es decir: no puede escapar!
) pero!
aún conserva su significado especial, por lo que se realiza la expansión de la historia.Sin embargo, cuando
!
le sigue un carácter de espacio, no se realiza la expansión del historial.Citando de
man bash
:fuente