Linuxの「スクリプト」コマンドの出力をクリーンアップする方法


35

Linuxの「スクリプト」コマンドhttp://www.linuxcommand.org/man_pages/script1.htmlを使用して、 いくつかの対話型セッションを追跡しています。からの出力ファイルには、バックスペースキーストロークを含む印刷できない文字が含まれています。

これらの出力ファイルを整理して、画面に表示されたものだけを含める方法はありますか?

または、対話型のシェルセッション(入力および出力)を記録する別の方法はありますか?


「または、対話型シェルセッション(入力および出力)を記録する別の方法はありますか?」asciinema.orgを知ってますか?
masterxilo

回答:


34

ファイルを表示したい場合は、を介して出力を送信できますcol -bp。これは制御文字を解釈します。必要に応じて、パイプスルーを少なくすることができます。

col -bp typescript | less -R

一部のシステムでcolは、ファイル名引数を受け入れないため、代わりに次の構文を使用します。

col -bp <typescript | less -R

1
私のシステムでcolは、ファイル名を受け入れないので、col -bp < typescript やりたいことをやりました。
アンドリュー

私にとってはうまくいきません、出力の一部をスクランブルします。
アレックス

1
私のシステムではless -Rcol -bp最初にパイピングするよりも出力が優れています。
ブライアンホーキンス

@BrianHawkins同意します。を使用col -bp <typescript | less -Rしても、色付きのコンソールは表示されません。を使用less -R typescriptすると、色付きのコンソールが表示されます!
トレバーボイドスミス

これは、でスクリプトをインタラクティブに表示する場合にのみ有効ですless
トレバーボイドスミス

18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

以下は、への文字列入力の解釈ですperl

  • s/pattern//gg入力文字列全体で置換を行うことを意味します(オプションは、最初の置換で停止するのではなく、すべてを行うことを意味します)入力文字列

正規表現パターンの解釈は次のとおりです。

  • \e 特別な「エスケープ」制御文字(ASCII 0x1A)と一致
  • ( そして )、グループの始まりと終わりです
  • |グループがN個のパターンのいずれかに一致できることを意味します。Nパターンは
    • [^\[\]] または
    • \[.*?[a-zA-Z] または
    • \].*?\a
  • [^\[\]] 手段
    • ない文字がされているわけではない文字のセットと一致[し、]
  • \[.*?[a-zA-Z] 手段
    • で始まる文字列に一致し、最初のアルファ文字まで[貪欲ではない.*?
  • \].*?\a 手段
    • で始まる文字列に一致し、「警告(ベル)文字」と呼ばれる特別な制御文字を]押す.*?まで貪欲でないことを行います。

1
私はまだ方法を理解する必要がありますが、これは実際に動作します;)
asdmin

@asdmin-基本的に、これは、出力から特定の制御文字を削除typescriptするperlプログラムに出力をエコーし​​、出力をunix colコマンドにパイプします。unix コマンド-bは、転写の「削除」キーアーティファクトを削除します。次に、出力をテキストファイルにパイプします。
ピーターノア

これはタイプスクリプトの最初の行の出力をスクランブルしますが、最良の答えです。
アレックス

これはいくつかのタイプスクリプトで非常にうまく機能するようです。受け入れられた回答によって生成される出力よりも確かに読みやすいです。
フェイクダッド

伝説の答え!
ザック

2

大量のscript出力を得るには、perlスクリプトを繰り返しハッキングします。それ以外の場合は、優れたエディターを使用して手動で編集します。

script特定の重要な瞬間(ホストがそれを待っているときなど)に画面に表示されたものを再現する方法で、出力から制御文字を削除する既存の自動化された方法はありそうにありませんユーザー入力の最初の文字を。

たとえば、を除く画面が空白になるAndrew $場合がありますrm /*。12回(必要以上に)入力してバックスペースを押した場合、画面の最後に表示される内容は、実行中のシェル、現在のstty設定(これはセッションの途中で変更される可能性があります)、おそらく他のいくつかの要因も含まれます。

上記は、入力および出力を継続的にキャプチャする自動化された方法に適用されます。主な代替手段は、セッション中の適切な時間に「スクリーンショット」を撮るか、スクリーンを切り取って貼り付けることです(これは、ユーザーガイドや日誌のメモなどで行います)。



2

cat filename制御文字を削除するために使用しました:-)


imoこれは、すべての制御文字を実際に削除するため、より良い回答です。
ナタナエルファーリー14

OSXでは、catは色制御文字を削除しません...
Nick

9
実際、catは制御文字をまったく削除せず、逐語的に出力し、端末はそれらを解釈します。タイプスクリプトがターミナルバッファに比べて短く、ターミナルからコピーアンドペーストするだけでよい場合は、これでうまくいくかもしれません。ただし、タイプスクリプトが大きい場合はあまり良くありません。
mc0e

1
同意した。これは何も削除しません。シェルがそれらを解釈できるようにするだけです。彼らはまだ存在しています。
ケントグラフ

2

場合は何を後にしていること(後にbashスクリプトにそれらを有効にするなど)、あなたのコマンドを記録することで、その合理的なハックを実行することでscript(1)、それが実行し、その後の内側

bash -x

その後grep、出力ファイル(通常は「typescript」)が「+」で始まる行を探します。正規表現^\+がトリックを行います。


2

出力をファイルに書き込みたい場合:

col -bp < typescript >>newfile

必要に応じて、unix2dosコマンドを使用してファイルをWindows形式に変換します


1
Ubuntu 14.04では、行の最初と最後に大量の迷惑メールが残ります。かなり読みやすいですが、本当にきれいではありません。
mc0e

2

col -bpは、必要に応じてバックスペースを処理します(AFAIK)。ただし、カラーエスケープシーケンスは破損します。可能であれば、最初にカラーシーケンスを削除してから、バックスペースを処理することをお勧めします。

これは非常に一般的なニーズであり、それに対する解決策がこれ以上ないことに驚いています。セッションをスクリプト化することは非常に一般的であり、誰かが手順を確認する必要があります。小さな入力ミスをすべて取り除き、エスケープシーケンスを色分けして、将来の参照のために手順の「クリーンな」スクリプトを作成します。シンプルなASCIIテキストを推奨。これは「人間が読める」ことによって意図されたものであり、非常に合理的なことだと思います。


1

dewtallが提供する答えを見つけましたPerlが利用できる環境にいる場合がUnixボード上の同様の質問に、スクリプトの出力から制御文字を削除するのにより効果的であることが。

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

制御文字を削除するには:

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


0

良い方法を見つけました。私のシステムでは、長い出力行に "^ M"(空白スペースの後にキャリッジリターンが続く)が散在しています。「^ M」は、ファイルをcatしたときにまったく表示されないヌル文字「^ @」にうまく置き換えることができます。

タイミングもキャプチャするため、ファイルを完全に再生するために、以下のコマンドを使用して「^ M」を完全に削除することはできません(scriptreplayはバイトをカウントするため)。

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

次のようにスクリプトコマンドを実行します。

script -t -f session.log 2>timing

だから、その後私がやることは:

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

最初の編集(リプレイ前)は、ファイル内のバイト数を保持します。2番目の編集(再生後)は、ランダムな場所の空白を取り除きます。(デフォルトでは、scriptreplayは「typescript」という名前の入力ファイルを探すため、「timing」の後に指定しなかったことに注意してください。)


-1

出力のdos2unixもトリックを行います


7
それを使用してタスクを実行する方法を説明できますか?
ベンN

-1

もう1つの解決策はstrings、ファイル(または標準入力)から印刷可能な文字のみを印刷するものを使用することです。

strings -n 1 filename

この-n 1オプションは、保存されるシーケンスの最小長を1に設定するため、印刷できない文字に囲まれた単一の印刷可能な文字も保存されます。

このアプローチの1つの考えられる欠点はstrings、印刷可能な文字の連続した文字列の間に改行が追加されることです。たとえば、コンテンツを含むファイル

Foo<SOMECONTROLCHAR>Bar

<SOMECONTROLCHAR>制御文字またはその他の印刷できない文字)は次のように返されます

Foo
Bar

コメントで提起された別の問題は、制御文字のシーケンスの一部が印刷可能文字と印刷不可文字の両方の組み合わせで構成され、このアプローチではそれらの一部のみが削除されることです。

ただし、strings質問で言及されているバックスペースのような制御文字を削除するのは良い仕事です。


stringsすべての印刷不能文字を削除しません。印刷可能な文字のシーケンスを識別して印刷します。それは同じことではありません。
CVn

@MichaelKjörling、あなたは正しい、デフォルトstringsでは最小長4のシーケンスのみを出力-n 1します。最小長を1に設定するオプションを追加することにより、答えを修正しました。これを指摘してくれてありがとう。
-justfortherec

答えは、stringsすべての非印刷可能文字を削除するという同じ主張を依然として行っているため、編集前と同じように間違っています。また、「一部のカラーコード」(および一般に制御コード)が印刷可能な文字と印刷できない文字の両方で構成されることが多いため、明らかに壊れています。たとえば、テキストの色を変更するための制御コードシーケンスがあるかもしれないESC[01;52mどこESCシングルエスケープ文字(バイト値27)があります。strings提案どおりに使用する[01;52mと、出力に残りますが、これは無意味です。
CVn

良い点、@MichaelKjörling。特に、カラーコードを使用した例は非常に残念でした。私の答えを改善するのを手伝ってくれてありがとう。編集はあなたの懸念に適切に対処していますか?strings他の回答のいくつかと同じ仕事をしないかもしれませんが、私見は質問で説明されている問題を解決するための有効なアプローチです。
justfortherec
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.