Como limpar a saída do comando 'script' do linux

35

Estou usando o comando 'script' do linux http://www.linuxcommand.org/man_pages/script1.html para rastrear algumas sessões interativas. Os arquivos de saída contêm caracteres não imprimíveis, incluindo minhas teclas de backspace.

Existe uma maneira de arrumar esses arquivos de saída para que eles contenham apenas o que foi exibido na tela?

Ou existe outra maneira de gravar uma sessão de shell interativa (entrada e saída)?

Andrew
fonte
"Ou existe outra maneira de gravar uma sessão de shell interativa (entrada e saída)?" Você conhece asciinema.org ?
Masterxilo

Respostas:

34

Se você deseja visualizar o arquivo, pode enviar a saída col -bp; isso interpreta os caracteres de controle. Então você pode canalizar menos, se quiser.

col -bp typescript | less -R

Em alguns sistemas colnão aceitariam um argumento de nome de arquivo, use esta sintaxe:

col -bp <typescript | less -R
Arcege
fonte
1
no meu sistema, colnão aceitaria um nome de arquivo, então aceitei col -bp < typescript e consegui o que queria.
19412 Andrew
Não funciona para mim, embaralha parte da saída.
23416 Alex
1
No meu sistema, less -Rpor si só, fornece uma saída melhor do que a tubulação col -bpprimeiro.
Brian Hawkins
@BrianHawkins, eu concordo. O uso col -bp <typescript | less -Rnão exibe o console colorido. O uso less -R typescriptexibe o console colorido!
Trevor Boyd Smith
isso só é bom se você deseja visualizar o script interativamente less.
Trevor Boyd Smith
18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

aqui está uma interpretação da entrada de string para perl:

  • s/pattern//gsignifica fazer uma substituição na gcadeia de entrada inteira (a opção significa fazer a coisa toda em vez de parar no primeiro substituto)

aqui está uma interpretação do padrão regex:

  • \e corresponde ao caractere de controle "escape" especial (ASCII 0x1A)
  • (e )são o começo e o fim de um grupo
  • |significa que o grupo pode corresponder a um dos N padrões. onde os padrões N são
    • [^\[\]] ou
    • \[.*?[a-zA-Z] ou
    • \].*?\a
  • [^\[\]] significa
    • corresponder a um conjunto de caracteres NÃO em que os caracteres não estão [e]
  • \[.*?[a-zA-Z] significa
    • corresponda a uma sequência iniciada por, em [seguida, faça um não ganancioso .*?até o primeiro caractere alfa
  • \].*?\a significa
    • corresponda a uma sequência que começa com ]e faça um não ganancioso .*?até atingir o caractere de controle especial chamado "o caractere de alerta (sino)"
Peter Nore
fonte
1
Eu ainda preciso descobrir como, mas isso realmente funciona;)
asdmin
@asdmin - Basicamente, isso faz eco da saída de typescriptpara um perlprograma que remove certos caracteres de controle da saída e canaliza a saída para o colcomando unix , cuja -bopção remove qualquer artefato de chave "excluir" na transcrição. Em seguida, canaliza a saída para um arquivo de texto.
Peter Nore
Isso embaralha a saída na primeira linha do texto datilografado para mim, mas é a melhor resposta.
23416 Alex
Isso parece funcionar muito bem com alguns tipos de texto; certamente é mais legível do que a saída produzida pela resposta aceita.
Fakedad # 23/17
resposta lendária!
zack
2

Para uma grande quantidade de scriptsaída, eu hackeava um script perl juntos iterativamente. Caso contrário, edite manualmente com um bom editor.

É improvável que exista um método automatizado existente para remover caracteres de controle da scriptsaída de uma maneira que reproduza o que foi exibido na tela em determinados momentos importantes (como quando o host estava esperando pelo primeiro caractere de alguma entrada do usuário).

Por exemplo, a tela pode ficar em branco, exceto Andrew $, se você digitar rm /*e pressionar a tecla backspace doze vezes (muito mais do que o necessário), o que é mostrado na tela no final depende de qual shell estava em execução, quais são as suas sttyconfigurações atuais ( que você pode alterar parcialmente durante uma sessão) e provavelmente alguns outros fatores também.

O acima se aplica a qualquer método automatizado de captura contínua de entrada e saída. A principal alternativa é tirar "capturas de tela" ou recortar e colar a tela em momentos apropriados durante a sessão (que é o que faço nos guias do usuário, notas para um diário, etc.).

RedGrittyBrick
fonte
2

Eu usei o cat filenameque remove os caracteres de controle :-)

Peeyush
fonte
imo, esta é uma resposta melhor, pois remove realmente todos os caracteres de controle.
Nathanael Farley
no OSX, gato não remove caracteres de controle de cor ...
Nick
9
Na verdade, cat não remove os caracteres de controle, mas os envia literalmente, e o terminal os interpreta. Isso pode funcionar para você se o seu texto digitado for curto em relação ao buffer do terminal e você puder simplesmente copiar e colar do terminal. Não é tão bom se o seu texto datilografado for grande.
Mc0e
1
Acordado. Isso não remove nada. Simplesmente permite que o shell os interprete. Eles ainda estão presentes.
Kentgrav 24/08
2

Se você deseja gravar seus comandos (por exemplo, transformá-los posteriormente em um script bash), é necessário executar um hack razoável e script(1), dentro dele, executar

bash -x

Depois, grepo arquivo de saída (normalmente "datilografado") procura linhas iniciando com um "+". A expressão regular ^\+fará o truque.

Yaron
fonte
2

Se você deseja gravar a saída em um arquivo:

col -bp < typescript >>newfile

use o comando unix2dos para converter o arquivo para o formato Windows, se desejar

amara
fonte
1
No Ubuntu 14.04, isso deixa muito lixo no início e no final das linhas. Bastante legível, mas não muito limpo.
Mc0e 5/06
2

col -bp processa os backspaces conforme desejado (AFAIK). Mas controla as seqüências de escape de cores. Pode ser bom remover as seqüências de cores primeiro e depois processar os backspaces, se possível.

Essa é uma necessidade muito comum e estou surpreso por não haver mais soluções para isso. É extremamente comum criar um script para uma sessão e alguém precisa revisar o procedimento. Você deseja eliminar todos os pequenos erros de digitação e seqüências de escape de cores para criar um script "limpo" do procedimento para referência futura. Texto ASCII simples preferido. Eu acho que é isso que se entende por "legível por humanos", e é uma coisa muito razoável de se fazer.

Aaron
fonte
1

Eu achei a resposta que dewtall forneceu a uma pergunta semelhante no quadro Unix para ser mais eficaz na remoção de caracteres de controle da saída do script, se você estiver em um ambiente em que o Perl esteja disponível.

roteiro de dewtall:

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

Para remover os caracteres de controle:

./dewtalls-script.pl < output-from-script-that-needs-control-characters-removed
rynemccall
fonte
1

https://github.com/RadixSeven/typescript2txt foi escrito para resolver esse problema.

Faz quatro anos desde a última vez que o atualizei / usei, mas não me lembro de ter feito algo sofisticado que ainda não deveria funcionar hoje.

Eponymous
fonte
0

Eu encontrei uma boa maneira de fazê-lo. No meu sistema, linhas de saída longas são salpicadas com "^ M" (espaço em branco seguido de retorno de carro). O "^ M" pode ser bem substituído pelo caractere nulo "^ @", que não é exibido quando você cria o arquivo.

Também capturo o tempo, portanto, para reproduzir o arquivo perfeitamente, não posso simplesmente remover "^ M" completamente usando os comandos abaixo (porque o scriptreplay conta bytes):

tr '\r' '\0' | sed 's/ \x0//g'

Eu executo meu comando de script assim:

script -t -f session.log 2>timing

Então, o que eu faço depois é:

cat session.log | tr '\r' '\0' > typescript 
scriptreplay -t timing | sed 's/ \x0//g'

A primeira edição (antes da reprodução) mantém o número de bytes no arquivo. A segunda edição (após a reprodução) se livra do espaço em branco em lugares aleatórios. (Observe que, por padrão, o scriptreplay procura o arquivo de entrada chamado "typescript", motivo pelo qual não o forneci após o "tempo".)

Khanan
fonte
-1

dos2unix na saída também fará o truque

Albert
fonte
7
Você poderia explicar como usá-lo para realizar a tarefa?
Ben N
-1

Uma outra solução é usar o stringsque imprime apenas caracteres imprimíveis de um arquivo (ou da entrada padrão):

strings -n 1 filename

A -n 1opção define o comprimento mínimo das seqüências a serem preservadas para uma e, assim, garante a preservação de caracteres imprimíveis únicos cercados por caracteres não imprimíveis.

Uma possível desvantagem dessa abordagem é que ela stringsadiciona quebras de linha entre cadeias contíguas de caracteres imprimíveis. Por exemplo, um arquivo com conteúdo

Foo<SOMECONTROLCHAR>Bar

(onde <SOMECONTROLCHAR>está o caractere de controle ou qualquer outro caractere não imprimível) seria retornado como

Foo
Bar

Outra questão levantada nos comentários é que algumas seqüências de caracteres de controle consistem em uma combinação de caracteres imprimíveis e não imprimíveis e essa abordagem remove apenas parte deles.

No entanto, stringsfaz um bom trabalho ao remover caracteres de controle como o backspace mencionado na pergunta.

justfortherec
fonte
stringsnão remove todos os caracteres não imprimíveis. Ele identifica e imprime seqüências de caracteres imprimíveis . Isso não é a mesma coisa.
um CVn
@ MichaelKjörling, você está certo, por padrão, stringsapenas imprime seqüências com um comprimento mínimo de 4. Corrigi minha resposta adicionando a -n 1opção que define o comprimento mínimo como 1. Obrigado por apontar isso.
justfortherec
A resposta ainda faz a mesma afirmação que stringsremove todos os caracteres não imprimíveis, por isso ainda está errada da mesma forma que estava antes da edição. Também está obviamente quebrado porque "alguns códigos de cores" (e códigos de controle em geral) geralmente consistem em caracteres imprimíveis e não imprimíveis. Por exemplo, uma sequência de código de controle para alterar a cor do texto pode estar ESC[01;52monde ESCestá o caractere de escape único (valor de byte 27). Usar stringscomo você sugere deixaria [01;52mna saída, o que não faz sentido.
precisa
Bom ponto, @ MichaelKjörling. Especialmente o exemplo com o código de cores foi muito infeliz. Obrigado por me ajudar a melhorar minha resposta. As edições tratam de suas preocupações adequadamente? stringspode não fazer o mesmo trabalho que algumas das outras respostas, mas IMHO é uma abordagem válida para resolver o problema descrito na pergunta.
precisa saber é o seguinte