Pode zsh acessar o stdout do último programa de execução?

13

Costumo usar find ou locate para descobrir caminhos.

(~) locate foobar.mmpz
/home/progo/lmms/projects/foobar.mmpz

O próximo passo é freqüentemente abrir ou manipular os arquivos. Em um caso feliz como acima, posso fazer isso:

(~) ls '!!'
ls 'locate foobar.mmpz'
/home/progo/lmms/projects/foobar.mmpz

Mas ninguém é muito feliz quando há muitas linhas de saída, algumas das quais podem não ser caminhos ou qualquer outra coisa desse tipo. Além disso, a execução de comandos potencialmente perdulários também não é tão elegante.

Haveria uma maneira de ligar o zsh para armazenar o stdout em uma matriz para manipulação posterior? Afinal, é o trabalho do shell redirecionar os fluxos para o usuário. Eu estou pensando que poderia armazenar o primeiro N e as últimas N linhas em uma variável para uso posterior imediato, como $? e outros.

Ok , isso é muito legal: link . Agora estou perguntando sobre o know-how do zsh (e portando o código para o zsh) para manipular esse tipo de captura após cada linha de execução.

    
por souser12345 26.02.2014 / 14:46

4 respostas

5

Não há recurso para capturar a saída da tela na maioria dos emuladores de terminal. Eu pareço lembrar o autor do xterm (o emulador de terminal de “referência”) afirmando que seria difícil de implementar. Mesmo que isso fosse possível, o shell teria que acompanhar onde o último prompt havia sido.

Assim, você não vai mais ter que executar o comando novamente, a menos que você use um mecanismo manual específico do terminal, como copiar e colar com o mouse no xterm ou com o teclado na Tela.

Seria altamente impraticável para o shell capturar automaticamente a saída de comandos, porque não é possível distinguir entre comandos que possuem terminal complexo e interações do usuário de comandos que simplesmente exibem caracteres imprimíveis.

Você pode executar novamente o comando e capturar sua saída. Existem várias maneiras de fazer cada um. Para reexecutar o comando, você pode usar:

  • !! de substituição do histórico - mais conveniente para digitar;
  • fc -e - , que pode ser usado em uma função.

Para capturar a saída, você pode usar a substituição de comandos ou uma função como a seguinte:

K () {
  lines=("${(f@)$(cat)}")
}
!! |K

Isso define a matriz lines como a saída do comando que é canalizado para ela.

    
por 27.02.2014 / 03:38
3

Aqui está um primeiro recorte de algo para colocar a última linha de saída em uma variável chamada $lastline .

precmd () {                                                                                                                                                                                                        
    exec 2>&- >&-
    lastline=$(tail -1 ~/.command.out) 
    sleep 0.1   # TODO: synchronize better
    exec > /dev/tty 2>&1
}

preexec() {
    exec > >(tee ~/.command.out&)
}

Isso usa o gancho preexec do zsh para executar exec com tee para armazenar uma cópia do stdout do comando, depois usa precmd para ler a saída armazenada e restaurar o stdout para ser apenas o terminal para mostrar o prompt .

Mas ainda precisa de algum trabalho. Por exemplo, como o stdout não é mais um terminal, programas como vim e less não funcionam corretamente.

Há algumas informações relacionadas úteis nessas perguntas:

por 26.02.2014 / 20:46
2

Você pode fazer isso apenas canalizando seus resultados para tee , que salva a saída em um arquivo e a exibe ao mesmo tempo.

Por exemplo, você poderia fazer isso, o que mostra sua saída como normal, mas também salva no arquivo /tmp/it

locate foobar.mmpz | tee /tmp/it

em seguida, gere esse arquivo e use-o para selecionar itens, por exemplo

cat /tmp/it | grep progo | grep lms

então, para usá-lo, você poderia fazer isso:

vi $(!!)

    
por 09.11.2017 / 14:07
1

Eu criei esta solução semiaberta:

alias -g ___='${"${(f@)$(eval "$(fc -ln -1)")}": -1}'

Isso permite que você escreva ___ em qualquer ponto na linha de comando. O comando anterior será executado novamente e o ___ será substituído pela última linha de sua saída. Exemplo de uso:

$ touch foo bar baz
$ ls -1
bar
baz
foo
$ vim ___

O último comando será expandido para vim foo .

Isso tem algumas arestas afiadas! Se você incluir ___ em um comando, mas o comando anterior também incluiu um ___ , o shell ficará em algum estado estranho por algum tempo. (Você pode sair deste estado imediatamente com Ctrl - C ). Você também não pode pressionar Tab para expandir o ___ , como acontece com !$ e outras construções. E, claro, se você quisesse fazer algo com uma linha de saída diferente da última, isso não ajudaria você.

(Eu escolhi o nome ___ porque é algo que eu nunca quis incluir como uma palavra em uma linha de comando, nem mesmo como argumento. Você poderia escolher um nome diferente, mas tome cuidado para não escolher algo que pode ser expandido para você inadvertidamente.)

    
por 05.11.2018 / 22:41