semelhante ao existente $_
que aprendi significa !-1:$
, gostaria de criar aliases para $__
, $___
e assim por diante, que se refiram ao 2º ou 3º comando -último. Eu tentei adicionar
alias "$__"='!-2:$'
no meu .zshrc.local
. Se possível, gostaria de escrever uma função zsh que devolva o primeiro argumento do enésimo último comando com base na quantidade de sublinhados.
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
Responder1
Esta funcionalidade já existe
Você não precisa de nada complicado para acessar a última palavra dos comandos anteriores. Basta pressionar ESC-.
(ou seja Alt, + .) ou ESC-_
(ou seja, Alt+ _). Isso invoca o comando do editorinsert-last-word
, que insere a última palavra da linha de comando anterior. Pressione a tecla novamente para obter a última palavra da linha de comando antes disso e assim por diante. Se você pressionar ESC-.
uma vez a mais, use C-_
(desfazer) para voltar à palavra que você tinha antes.
Este comando não está vinculado a uma chave por padrão no modo vi, mas você pode vinculá-lo com bindkey
.
Você pode passar um argumento numérico para obter uma palavra diferente: positivo para começar à direita (1 é a última palavra), zero ou negativo para começar à esquerda (0 é a primeira palavra que geralmente é o nome do comando, 1 é o palavra depois daquela que é o primeiro argumento, etc.). Por exemplo ESC . ESC - ESC 1 ESC .
, insere o primeiro argumento do penúltimo comando.
Muitas variações deste comando são possíveis definindo seu próprio widget em torno de zle insert-last-word
. Zsh vem comcopy-earlier-word
esmart-insert-last-word
que você pode achar útil para usar como está ou como exemplos de código.
Se você realmente deseja $__
expandir para a última palavra do comando anterior, darei algumas soluções abaixo, mas primeiro preciso explicar o que está acontecendo.
Por que sua tentativa não está funcionando
Primeiro, você não está definindo o que pensa que está definindo. alias "$__"=…
define um alias cujo nome é o valor atual da variável __
no momento em que a definição do alias é executada. Provavelmente está vazio, então você está executando alias ='!-2:$'
o que procura por um comando chamado '!-2:$'
no caminho de pesquisa (o=
expansãoparte da expansão do nome do arquivo). Para definir um alias chamado $__
, você precisa passar $__
para o comando alias, por exemplo, com alias '$__'=…
ou alias \$__=…
.
Em segundo lugar, um alias só é expandido na posição de comando, ou seja, como a primeira palavra de um comando (após quaisquer atribuições e redirecionamentos de variáveis iniciais). Para que esse alias seja útil, ele precisaria ser umapelido global:alias -g '$__'=…
Terceiro, esse alias não faria nada de útil, porque a expansão do alias ocorre após a expansão do histórico.
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
não “representa” !-1:$
. $_
e !-1:$
são duas maneiras de acessar as mesmas informações em casos comuns. Você pode dizer que $_
“é um alias” de !-1:$
, ou inversamente, que !-1:$
“é um alias” de $_
, mas isso é usar “alias” em seu sentido geral em inglês, não no sentido técnico de aliases de shell, e é impreciso porque os dois não t sempre o mesmo valor. !-1:$
é umexpansão da história( !
) construção que se expande para oúltima palavra( :$
) dolinha de comando anterior( -1
). $_
é umparameter expansion
usando o parâmetro_
que o shell define como o último argumento do comando anterior. Faz diferença se você executar linhas de comando que não sejam exatamente um comando simples, por exemplo:
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
Definindo $__
por comando
Você pode definir umfunção de armadilhachamadoTRAPDEBUG
que é executado antes de executar cada comando. Lembre-se do valor atual de $_
(observe que você deve fazer isso primeiro, porque o primeiro comando dentro do trap irá sobrescrever _
) e, em seguida, “desloque” as variáveis com múltiplos sublinhados.
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
nem sempre será o mesmo que $_
, porque a armadilha de depuração não é executada exatamente nas mesmas circunstâncias que a definem _
, mas é bem próxima.
Definindo $__
por linha de comando
Você pode registrar umfunção de ganchopara ser executado antes ou depois de inserir uma linha de comando. Neste caso, ouprecmd
oupreexec
. Eles são executados antes e depois da execução de um comando, respectivamente.
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
eu usohistorywords
para obter a última palavra da linha de comando. Eu guardo _1
porque _
já está levado. E a função “desloca” as variáveis do histórico da última palavra em um.
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one