De manera similar al existente $_
que aprendí que significa !-1:$
, me gustaría crear alias para $__
, $___
etc., que se refieran al segundo o tercer último comando. He intentado agregar
alias "$__"='!-2:$'
en mi .zshrc.local
. Si es posible, me gustaría escribir una función zsh que devuelva el primer argumento del enésimo último comando en función de la cantidad de guiones bajos.
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
Respuesta1
Esta funcionalidad ya existe
No necesitas nada complicado para acceder a la última palabra de los comandos anteriores. Simplemente presione ESC-.
(es decir Alt, + .) o ESC-_
(es decir, Alt+ _). Esto invoca el comando del editor.insert-last-word
, que inserta la última palabra de la línea de comando anterior. Presione la tecla nuevamente para obtener la última palabra de la línea de comando anterior a esa, y así sucesivamente. Si presiona ESC-.
demasiadas veces, use C-_
(deshacer) para volver a la palabra que tenía justo antes.
Este comando no está vinculado a una clave de forma predeterminada en el modo vi, pero puede vincularlo con bindkey
.
Puede pasar un argumento numérico para obtener una palabra diferente: positivo para comenzar por la derecha (1 es la última palabra), cero o negativo para comenzar por la izquierda (0 es la primera palabra que generalmente es el nombre del comando, 1 es la palabra después de la que es el primer argumento, etc.). Por ejemplo, ESC . ESC - ESC 1 ESC .
inserta el primer argumento del penúltimo comando.
Son posibles muchas variaciones de este comando definiendo su propio widget zle insert-last-word
. Zsh viene concopy-earlier-word
ysmart-insert-last-word
que puede resultarle útil para utilizarlo tal cual o como ejemplo de código.
Si realmente desea $__
expandirse a la última palabra del comando anterior menos uno, le daré algunas soluciones a continuación, pero primero necesito explicar qué está pasando.
Por qué tu intento no funciona
Primero, no estás definiendo lo que crees que estás definiendo. alias "$__"=…
define un alias cuyo nombre es el valor actual de la variable __
en el momento en que se ejecuta la definición del alias. Probablemente esté vacío, por lo que está ejecutando alias ='!-2:$'
el cual busca un comando llamado '!-2:$'
en la ruta de búsqueda (el=
expansiónparte de la expansión del nombre de archivo). Para definir un alias llamado $__
, debe pasar $__
al comando alias, por ejemplo, con alias '$__'=…
o alias \$__=…
.
En segundo lugar, un alias sólo se expande en la posición de comando, es decir, como la primera palabra de un comando (después de cualquier asignación de variable principal y redirecciones). Para que este alias sea útil, tendría que ser unalias global:alias -g '$__'=…
En tercer lugar, este alias no haría nada útil, porque la expansión del alias ocurre después de la expansión del historial.
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
no “representa” !-1:$
. $_
y !-1:$
son dos formas de acceder a la misma información en casos comunes. Puedes decir que $_
“es un alias” de !-1:$
o, a la inversa, que !-1:$
“es un alias” de $_
, pero eso es usar “alias” en su sentido general en inglés, no en el sentido técnico de alias de shell, y es impreciso porque los dos no Siempre tiene el mismo valor. !-1:$
es unexpansión de la historia( !
) constructo que se expande hasta elultima palabra( :$
) dellínea de comando anterior( -1
). $_
es unparameter expansion
usando el parámetro_
que el shell establece como el último argumento del comando anterior. Hay una diferencia si ejecuta líneas de comando que no son exactamente un comando simple, por ejemplo:
darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different
Definición $__
por comando
Puedes definir unfunción de trampallamadoTRAPDEBUG
que se ejecuta antes de ejecutar cada comando. Recuerde el valor actual de $_
(tenga en cuenta que debe hacer esto primero, porque el primer comando dentro de la trampa sobrescribirá _
), luego "desplace" las variables de guión bajo múltiple.
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
no siempre será el mismo que $_
, porque la trampa de depuración no se ejecuta exactamente en las mismas circunstancias en las que se _
establece, pero está bastante cerca.
Definición $__
por línea de comando
Puedes registrar unfunción de ganchoejecutar antes o después de ingresar una línea de comando. En este caso, ya seaprecmd
opreexec
. Se ejecutan antes y después de ejecutar un comando respectivamente.
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
yo suelohistorywords
para obtener la última palabra de la línea de comando. Lo guardo _1
porque _
ya está usado. Y la función "desplaza" las variables del historial de la última palabra en uno.
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one