Cómo limpiar la salida del comando 'script' de Linux

35

Estoy usando el comando de Linux 'script' http://www.linuxcommand.org/man_pages/script1.html para rastrear algunas sesiones interactivas. Los archivos de salida que contienen caracteres no imprimibles, incluidas mis pulsaciones de tecla de retroceso.

¿Hay alguna forma de ordenar estos archivos de salida para que solo contengan lo que se muestra en la pantalla?

¿O hay otra forma de grabar una sesión de shell interactiva (entrada y salida)?

Andrés
fuente
"¿O hay otra forma de grabar una sesión de shell interactiva (entrada y salida)?" ¿Conoces asciinema.org ?
masterxilo

Respuestas:

34

Si desea ver el archivo, puede enviar la salida col -bp; Esto interpreta los caracteres de control. Entonces puedes pasar menos, si quieres.

col -bp typescript | less -R

En algunos sistemas colno aceptaría un argumento de nombre de archivo, use esta sintaxis en su lugar:

col -bp <typescript | less -R
Arcege
fuente
1
en mi sistema, colno aceptaría un nombre de archivo, así que lo hice col -bp < typescript y obtuve lo que quería.
Andrew
No funciona para mí, codifica parte de la salida.
Alex
1
En mi sistema, less -Rpor sí mismo, proporciona una mejor salida que pasar col -bpprimero.
Brian Hawkins el
@BrianHawkins estoy de acuerdo. El uso col -bp <typescript | less -Rno muestra la consola coloreada. ¡El uso less -R typescriptmuestra la consola coloreada!
Trevor Boyd Smith
esto solo es bueno si desea ver el script de forma interactiva less.
Trevor Boyd Smith
18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

Aquí hay alguna interpretación de la entrada de cadena a perl:

  • s/pattern//gsignifica hacer una sustitución en toda la gcadena de entrada (la opción significa hacer todo en lugar de detenerse en el primer sustituto)

Aquí hay alguna interpretación del patrón regex:

  • \e coincide con el carácter de control especial de "escape" (ASCII 0x1A)
  • (y )son el principio y el final de un grupo
  • |significa que el grupo puede coincidir con uno de los N patrones. donde están los patrones N
    • [^\[\]] o
    • \[.*?[a-zA-Z] o
    • \].*?\a
  • [^\[\]] medio
    • coincide con un conjunto de caracteres NO donde están los caracteres no [y]
  • \[.*?[a-zA-Z] medio
    • hacer coincidir una cadena que comience con y [luego hacer una no codiciosa .*?hasta el primer carácter alfa
  • \].*?\a medio
    • ]haga coincidir una cadena que comience con y luego haga una acción no codiciosa .*?hasta que toque el carácter de control especial llamado "el carácter de alerta (campana)"
Peter Nore
fuente
1
Todavía necesito averiguar cómo, pero esto realmente funciona;)
asdmin
@asdmin: Básicamente, esto hace eco de la salida de typescriptun perlprograma que elimina ciertos caracteres de control de la salida, luego canaliza la salida al colcomando unix , cuya -bopción elimina cualquier artefacto clave "eliminar" en la transcripción. Luego canaliza la salida a un archivo de texto.
Peter Nore
Esto codifica la salida en la primera línea del mecanografiado para mí, pero es la mejor respuesta.
Alex
Esto parece funcionar muy bien con algunos tipos de letra; ciertamente es más legible que la salida producida por la respuesta aceptada.
fakedad
respuesta legendaria!
zack
2

Para una gran cantidad de scriptresultados, piratearía un script perl juntos de forma iterativa. De lo contrario, edite a mano con un buen editor.

Es poco probable que exista un método automatizado existente para eliminar los caracteres de control de la scriptsalida de una manera que reproduzca lo que se mostró en la pantalla en ciertos momentos importantes (como cuando el host estaba esperando ese primer carácter de alguna entrada del usuario).

Por ejemplo, la pantalla puede estar en blanco, excepto que Andrew $, si luego escribió rm /*y presionó retroceso doce veces (mucho más de lo necesario), lo que se muestra en la pantalla al final de eso depende de qué shell se estaba ejecutando, cuáles son sus sttyconfiguraciones actuales ( que podría cambiar a mitad de una sesión) y probablemente también otros factores.

Lo anterior se aplica a cualquier método automatizado de captura continua de entrada y salida. La alternativa principal es tomar "capturas de pantalla" o cortar y pegar la pantalla en los momentos apropiados durante la sesión (que es lo que hago para las guías de usuario, notas para un registro diario, etc.).

RedGrittyBrick
fuente
2

Utilicé lo cat filenameque elimina los caracteres de control :-)

Peeyush
fuente
Esta es una respuesta mejor, ya que realmente elimina todos los caracteres de control.
Nathanael Farley
en OSX, cat no elimina los caracteres de control de color ...
Nick
99
En realidad, cat no elimina los caracteres de control en absoluto, sino que los genera textualmente, y el terminal los interpreta. Eso podría funcionar para usted si su mecanografiado es corto en relación con el búfer de su terminal y simplemente puede copiar y pegar desde el terminal. Sin embargo, no es tan bueno si su mecanografiado es grande.
mc0e
1
Convenido. Esto no elimina nada. Simplemente permite que el shell los interprete. Todavía están presentes
Kentgrav
2

Si lo que buscas es grabar tus comandos (por ejemplo, para luego convertirlos en un script bash), entonces debes ejecutar un hack razonable script(1), luego dentro de él ejecutar

bash -x

Luego, grepel archivo de salida (generalmente "mecanografiado") busca líneas que comiencen con un "+". La expresión regular ^\+hará el truco.

Yaron
fuente
2

Si desea escribir la salida en un archivo:

col -bp < typescript >>newfile

use el comando unix2dos para convertir el archivo al formato de Windows si lo desea

amara
fuente
1
En Ubuntu 14.04, eso deja mucha basura al comienzo y al final de las líneas. Muy legible, pero no muy limpio.
mc0e
2

col -bp procesa los espacios de retroceso según lo deseado (AFAIK). Pero destruye las secuencias de escape de color. Puede ser bueno eliminar primero las secuencias de color, luego procesar los espacios de retroceso, si es posible.

Esta es una necesidad muy común, y me sorprende que no haya más soluciones. Es extremadamente común escribir una sesión en un script, entonces alguien tiene la necesidad de revisar el procedimiento. Desea eliminar todos los pequeños errores de escritura y secuencias de escape de color para crear una secuencia de comandos "limpia" del procedimiento para referencia futura. Texto ASCII simple preferido. Creo que esto es lo que se entiende por "legible por humanos", y es algo muy razonable de hacer.

Aaron
fuente
1

Encontré que la respuesta que dewtall proporcionó a una pregunta similar en el tablero de Unix es más efectiva para eliminar los caracteres de control de la salida del script si se encuentra en un entorno donde Perl está disponible para usted.

guión 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 eliminar los caracteres de control:

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

https://github.com/RadixSeven/typescript2txt se escribió para resolver este problema.

Han pasado 4 años desde la última vez que lo actualicé / usé, pero no recuerdo haber hecho nada elegante que todavía no debería funcionar hoy.

Epónimo
fuente
0

Encontré una buena manera de hacerlo. En mi sistema, las líneas de salida largas están salpicadas con "^ M" (espacio en blanco seguido de retorno de carro). La "^ M" se puede reemplazar muy bien con el carácter nulo "^ @", que no se muestra en absoluto cuando se captura el archivo.

También capturo el tiempo, así que para reproducir el archivo perfectamente, no puedo simplemente eliminar "^ M" completamente usando los comandos a continuación (porque scriptreplay cuenta bytes):

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

Ejecuto mi comando de script de esta manera:

script -t -f session.log 2>timing

Entonces, lo que hago después es:

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

La primera edición (antes de la reproducción) retiene el número de bytes en el archivo. La segunda edición (después de la repetición) elimina el espacio en blanco en lugares aleatorios. (Tenga en cuenta que, de forma predeterminada, scriptreplay busca el archivo de entrada llamado "typecript", por lo que no lo proporcioné después de "timing").

Khanan
fuente
-1

dos2unix en la salida también hará el truco

Albert
fuente
77
¿Podría explicar cómo usarlo para realizar la tarea?
Ben N
-1

Otra solución es usar el stringsque imprime solo caracteres imprimibles de un archivo (o de una entrada estándar):

strings -n 1 filename

La -n 1opción establece la longitud mínima de las secuencias que se conservarán en una y, por lo tanto, garantiza que incluso los caracteres imprimibles individuales rodeados de caracteres no imprimibles se conserven.

Una posible desventaja de este enfoque es que stringsagrega saltos de línea entre cadenas contiguas de caracteres imprimibles. Por ejemplo, un archivo con contenido

Foo<SOMECONTROLCHAR>Bar

(donde <SOMECONTROLCHAR>está el carácter de control o cualquier otro carácter no imprimible) se devolvería como

Foo
Bar

Otra cuestión planteada en los comentarios es que algunas secuencias de caracteres de control consisten en una combinación de caracteres imprimibles y no imprimibles, y este enfoque solo eliminaría parte de ellos.

Sin embargo, stringshace un buen trabajo al eliminar caracteres de control como el retroceso mencionado en la pregunta.

justfortherec
fuente
stringsno elimina todos los caracteres no imprimibles. Identifica e imprime secuencias de caracteres imprimibles . Eso no es lo mismo.
un CVn
@ MichaelKjörling, tiene razón, por defecto stringssolo imprime secuencias de una longitud mínima de 4. He corregido mi respuesta agregando la -n 1opción que establece la longitud mínima en 1. Gracias por señalar esto.
justfortherec
La respuesta todavía hace la misma afirmación que stringselimina todos los caracteres no imprimibles, por lo que sigue siendo incorrecta de la misma manera que antes de la edición. También está obviamente roto porque "algunos códigos de color" (y los códigos de control en general) a menudo consisten en caracteres imprimibles y no imprimibles. Por ejemplo, una secuencia de código de control para cambiar el color del texto podría ser ESC[01;52mdónde ESCestá el carácter de escape único (valor de byte 27). Usar stringscomo sugiere dejaría [01;52men la salida, lo que no tiene sentido.
un CVn
Buen punto, @ MichaelKjörling. Especialmente el ejemplo con el código de color fue muy desafortunado. Gracias por ayudarme a mejorar mi respuesta. ¿Las ediciones abordan sus inquietudes adecuadamente? stringsPuede que no haga el mismo trabajo que algunas de las otras respuestas, pero en mi humilde opinión, es un enfoque válido para resolver el problema descrito en la pregunta.
justfortherec