Configurar alias para un patrón de expansión del historial

Configurar alias para un patrón de expansión del historial

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-wordysmart-insert-last-wordque 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 expansionusando 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 trampallamadoTRAPDEBUGque 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

$_1no 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 seaprecmdopreexec. 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 suelohistorywordspara obtener la última palabra de la línea de comando. Lo guardo _1porque _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

información relacionada