Comment nettoyer la sortie de la commande linux 'script'

35

J'utilise la commande linux 'script' http://www.linuxcommand.org/man_pages/script1.html pour suivre certaines sessions interactives. Les fichiers de sortie qui contiennent des caractères non imprimables, y compris mes frappes de retour arrière.

Existe-t-il un moyen de ranger ces fichiers de sortie afin qu'ils ne contiennent que ce qui était affiché à l'écran?

Ou existe-t-il un autre moyen d'enregistrer une session shell interactive (entrée et sortie)?

Andrew
la source
"Ou existe-t-il un autre moyen d'enregistrer une session shell interactive (entrée et sortie)?" Connaissez-vous asciinema.org ?
masterxilo

Réponses:

34

Si vous souhaitez afficher le fichier, vous pouvez envoyer la sortie via col -bp; cela interprète les caractères de contrôle. Ensuite, vous pouvez passer moins, si vous le souhaitez.

col -bp typescript | less -R

Sur certains systèmes coln'accepteraient pas un argument de nom de fichier, utilisez plutôt cette syntaxe:

col -bp <typescript | less -R
Arcege
la source
1
sur mon système, coln'accepterait pas un nom de fichier, alors je l'ai fait col -bp < typescript et j'ai obtenu ce que je voulais.
Andrew
Ne fonctionne pas pour moi, brouille une partie de la sortie.
Alex
1
Sur mon système less -Ren lui-même, il fournit un meilleur rendement que la tuyauterie en col -bppremier.
Brian Hawkins
@ BrianHawkins je suis d'accord. L'utilisation col -bp <typescript | less -Rn'affiche pas la console colorisée. L'utilisation less -R typescriptaffiche la console colorisée!
Trevor Boyd Smith
ce n'est bon que si vous souhaitez afficher le script de manière interactive dans less.
Trevor Boyd Smith,
18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

voici une interprétation de la chaîne entrée perl:

  • s/pattern//gsignifie faire une substitution sur la totalité (l' goption signifie faire toute la chose au lieu de s'arrêter sur le premier substitut) chaîne d'entrée

voici une interprétation du modèle d'expression régulière:

  • \e correspondre au caractère de contrôle "d'échappement" spécial (ASCII 0x1A)
  • (et )sont le début et la fin d'un groupe
  • |signifie que le groupe peut correspondre à l'un des N modèles. où les N modèles sont
    • [^\[\]] ou
    • \[.*?[a-zA-Z] ou
    • \].*?\a
  • [^\[\]] veux dire
    • correspondre à un ensemble de caractères NOT où se trouvent les caractères not [et]
  • \[.*?[a-zA-Z] veux dire
    • correspondre à une chaîne commençant par [puis faire un non-gourmand .*?jusqu'au premier caractère alpha
  • \].*?\a veux dire
    • faire correspondre une chaîne qui commence par ]puis faire un non-gourmand .*?jusqu'à ce que vous frappiez le caractère de contrôle spécial appelé "le caractère d'alerte (cloche)"
Peter Nore
la source
1
J'ai encore besoin de comprendre comment, mais cela fonctionne vraiment;)
asdmin
@asdmin - Fondamentalement, cela fait écho à la sortie de typescriptdans un perlprogramme qui supprime certains caractères de contrôle de la sortie, puis redirige la sortie vers la colcommande unix , dont l' -boption supprime tous les artefacts de clé "supprimer" dans la transcription. Il dirige ensuite la sortie vers un fichier texte.
Peter Nore
Cela brouille la sortie dans la première ligne du texte dactylographié pour moi, mais c'est la meilleure réponse.
Alex
Cela semble très bien fonctionner avec certains scripts de saisie; c'est certainement plus lisible que la sortie produite par la réponse acceptée.
fakedad
réponse légendaire!
zack
2

Pour une grande quantité de scriptsortie, je piraterais un script perl ensemble de manière itérative. Sinon, éditez à la main avec un bon éditeur.

Il est peu probable qu'il existe une méthode automatisée existante pour supprimer les caractères de contrôle de la scriptsortie d'une manière qui reproduit ce qui était affiché à l'écran à certains moments importants (comme lorsque l'hôte attendait le premier caractère d'une entrée utilisateur).

Par exemple, l'écran peut être vide à l'exception de Andrew $, si vous avez ensuite tapé rm /*et appuyé douze fois en arrière (beaucoup plus que nécessaire), ce qui s'affiche à l'écran à la fin de cela dépend du shell en cours d'exécution, de vos sttyparamètres actuels ( que vous pourriez changer en cours de session) et probablement d'autres facteurs également.

Ce qui précède s'applique à toute méthode automatisée de capture continue d'entrée et de sortie. L'alternative principale consiste à prendre des «captures d'écran» ou à couper et coller l'écran à des moments appropriés pendant la session (c'est ce que je fais pour les guides de l'utilisateur, les notes pour un journal de bord, etc.).

RedGrittyBrick
la source
2

J'ai utilisé cat filenamece qui supprime les caractères de contrôle :-)

Peeyush
la source
imo c'est une meilleure réponse, car elle supprime vraiment tous les caractères de contrôle.
Nathanael Farley
sur OSX, le chat ne supprime pas les caractères de contrôle des couleurs ...
Nick
9
En fait, cat ne supprime pas du tout les caractères de contrôle, il les affiche plutôt textuellement et le terminal les interprète ensuite. Cela pourrait fonctionner pour vous si votre dactylographie est courte par rapport à votre tampon de terminal et que vous pouvez simplement copier et coller à partir du terminal. Pas si bon si votre dactylographie est volumineuse.
mc0e
1
D'accord. Cela ne supprime rien. Il permet simplement au shell de les interpréter. Ils sont toujours présents.
Kentgrav
2

Si ce que vous cherchez est d'enregistrer vos commandes (par exemple pour les transformer plus tard en un script bash), alors un hack raisonnable est à exécuter script(1), puis à l'intérieur

bash -x

Ensuite, greple fichier de sortie (généralement "dactylographié") recherchant des lignes commençant par un "+". L'expression régulière ^\+fera l'affaire.

Yaron
la source
2

Si vous souhaitez écrire la sortie dans un fichier:

col -bp < typescript >>newfile

utilisez la commande unix2dos pour convertir le fichier au format Windows si vous le souhaitez

amara
la source
1
Sur Ubuntu 14.04, cela laisse beaucoup de déchets au début et à la fin des lignes. Assez lisible, mais pas vraiment propre.
mc0e
2

col -bp traite les espaces arrière comme souhaité (AFAIK). Mais cela réduit les séquences d'échappement de couleur. Il peut être judicieux de supprimer d'abord les séquences de couleurs, puis de traiter les espaces arrière, si possible.

Il s'agit d'un besoin très courant et je suis surpris qu'il n'y ait pas d'autres solutions. Il est extrêmement courant de scénariser une session, alors quelqu'un a besoin de revoir la procédure. Vous voulez supprimer toutes les petites erreurs de frappe et les séquences d'échappement de couleur pour créer un script "propre" de la procédure pour référence future. Texte ASCII simple préféré. Je pense que c'est ce que veut dire "lisible par l'homme", et c'est une chose très raisonnable à faire.

Aaron
la source
1

J'ai trouvé que la réponse fournie par dewtall à une question similaire sur la carte Unix était plus efficace pour supprimer les caractères de contrôle de la sortie du script si vous êtes dans un environnement où Perl est à votre disposition.

le script 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;
}

Pour supprimer les caractères de contrôle:

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

https://github.com/RadixSeven/typescript2txt a été écrit pour résoudre ce problème.

Cela fait 4 ans que je l'ai mis à jour / utilisé pour la dernière fois, mais je ne me souviens pas avoir fait quelque chose d'extraordinaire qui ne devrait pas encore fonctionner aujourd'hui.

Éponyme
la source
0

J'ai trouvé un bon moyen de le faire. Sur mon système, les longues lignes de sortie sont saupoudrées de "^ M" (espace vide suivi d'un retour chariot). Le "^ M" peut être joliment remplacé par le caractère nul "^ @", qui ne s'affiche pas du tout lorsque vous cat le fichier.

Je capture également le timing, donc pour pouvoir rejouer le fichier parfaitement, je ne peux pas simplement supprimer complètement "^ M" en utilisant les commandes ci-dessous (car scripttreplay compte des octets):

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

J'exécute ma commande de script comme ceci:

script -t -f session.log 2>timing

Donc, ce que je fais après, c'est:

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

La première édition (avant la relecture) conserve le nombre d'octets dans le fichier. Le deuxième montage (après la relecture) supprime les espaces blancs à des endroits aléatoires. (Notez que par défaut, scripttreplay recherche le fichier d'entrée nommé "typescript", c'est pourquoi je ne l'ai pas fourni après "timing".)

Khanan
la source
-1

dos2unix sur la sortie fera aussi l'affaire

Albert
la source
7
Pourriez-vous expliquer comment l'utiliser pour accomplir la tâche?
Ben N
-1

Une autre solution consiste à utiliser stringsqui imprime uniquement des caractères imprimables à partir d'un fichier (ou d'une entrée standard):

strings -n 1 filename

L' -n 1option définit la longueur minimale des séquences à conserver à un et garantit ainsi que même les caractères imprimables simples entourés de caractères non imprimables sont préservés.

Un inconvénient possible de cette approche est l' stringsajout de sauts de ligne entre les chaînes contiguës de caractères imprimables. Par exemple un fichier avec du contenu

Foo<SOMECONTROLCHAR>Bar

(où <SOMECONTROLCHAR>est le caractère de contrôle ou tout autre caractère non imprimable) serait retourné comme

Foo
Bar

Un autre problème soulevé dans les commentaires est que certaines séquences de caractères de contrôle consistent en une combinaison de caractères imprimables et non imprimables et cette approche n'en supprimerait qu'une partie.

Cependant, stringsfait un bon travail de suppression des caractères de contrôle comme le retour arrière mentionné dans la question.

justfortherec
la source
stringsne supprime pas tous les caractères non imprimables. Il identifie et imprime des séquences de caractères imprimables . Ce n'est pas la même chose.
un CVn du
@ MichaelKjörling, vous avez raison, par défaut, stringsimprime uniquement des séquences d'une longueur minimale de 4. J'ai corrigé ma réponse en ajoutant l' -n 1option qui définit la longueur minimale à 1. Merci de l'avoir signalé.
justfortherec du
La réponse fait toujours la même affirmation qui stringssupprime tous les caractères non imprimables, elle est donc toujours erronée de la même manière qu'elle était avant la modification. Il est aussi manifestement cassé parce que "certains codes couleur" (et les codes de contrôle en général) sont souvent composés de caractères imprimables et non imprimables. Par exemple, une séquence de codes de contrôle pour changer la couleur du texte peut être ESC[01;52moù se ESCtrouve le caractère d'échappement unique (valeur d'octet 27). Utiliser stringscomme vous le laisseriez [01;52mdans la sortie, ce qui n'a aucun sens.
un CVn du
Bon point, @ MichaelKjörling. Surtout l'exemple avec le code couleur était très regrettable. Merci de m'avoir aidé à améliorer ma réponse. Les modifications répondent-elles correctement à vos préoccupations? stringspourrait ne pas faire le même travail que certaines des autres réponses, mais à mon humble avis, c'est une approche valable pour résoudre le problème décrit dans la question.
justfortherec le