$ _ vs! $. Último argumento del comando anterior y redirección de salida

28

La pregunta es sobre variables especiales. La documentación dice:

!!:$

designa el último argumento del comando anterior . Esto puede acortarse a! $.


( $_, un guión bajo). Al iniciar el shell, establezca el nombre de ruta absoluto utilizado para invocar el shell o el script de shell que se ejecuta como se pasa en el entorno o la lista de argumentos. Posteriormente, se expande hasta el último argumento del comando anterior después de la expansión. Establezca también el nombre de ruta completo utilizado para invocar cada comando ejecutado y colocado en el entorno exportado a ese comando.

Debe haber alguna diferencia que no pueda captar, porque:

$ echo "hello" > /tmp/a.txt
$ echo "!$"
echo "/tmp/a.txt"
/tmp/a.txt

$ echo "hello" > /tmp/a.txt
$ echo $_
hello

¿Cuál es la diferencia?

Telar
fuente
44
! $ es expansión de historial, no una variable especial, por lo que supongo que el código bash los maneja de manera diferente.
Jeff Schaller
2
No tengo una respuesta definitiva a esta pregunta, pero: ① El lenguaje de comandos Bourne es uno de, tal vez el lenguaje de programación menos internamente consistente sigue siendo ampliamente utilizado hoy. Intentar deducir principios generales no te llevará a ninguna parte. Solo tienes que memorizar todas las reglas especiales. Lo siento. ② Observe las palabras "después de la expansión", inmediatamente después de la frase que resaltó, en la definición de $_. Eso es crucial Es posible que no explique la diferencia que lo desconcierta, pero explica muchas otras formas $_y !$no son lo mismo.
zwol

Respuestas:

32

!$es un designador de palabras de expansión de la historia, se expande hasta la última palabra del comando anterior en la historia . IOW, la última palabra de la entrada anterior en la historia. Esta palabra suele ser el último argumento para ordenar, pero no en caso de redirección. En:

echo "hello" > /tmp/a.txt

todo el comando 'echo "hello" > /tmp/a.txt'apareció en la historia, y /tmp/a.txtes la última palabra de ese comando.

_es un parámetro de shell, se expande al último argumento del comando anterior. Aquí, la redirección no es parte de los argumentos pasados ​​al comando, por lo que solo se hellopasa el argumento echo. Por eso se $_expandió a hello.

_ no es uno de los parámetros especiales estándar shell . Funciona en bash, zsh, mkshy dashsólo cuando interactiva, ksh93sólo cuando dos comandos están en líneas separadas:

$ echo 1 && echo $_
1
/usr/bin/ksh

$ echo 1
1
$ echo $_
1
Cuonglm
fuente
1
Un efecto de la !$expansión frente al $_parámetro es que echo $_siempre se muestra en el historial como echo $_, mientras que echo !$muestra el valor al que se expandió. Por ejemplo , echo one twoluego echo !$, presionando hacia arriba se muestra echo two.
Jacktose