シェルスクリプトを使用して複数のファイルの特定の文字列を解析する方法

シェルスクリプトを使用して複数のファイルの特定の文字列を解析する方法

私はesp32プロジェクトを進行中で、すべてのesp32 uartデバッグ出力を複数のファイルに記録しています。ある時点で以前のバージョンがクラッシュし、出力は次のようになります。

エキスパート瞑想エラー:コア0でパニックが発生しました(キャッシュは無効になっていますが、キャッシュメモリ領域にアクセスしました)。

コア 0 レジスタダンプ: PC: 0x40008150 PS: 0x00060034 A0: 0x8008225c A1: 0x3ffb0670 A2: 0x3f40117c A3:
0x00000000 A4: 0x0 00000
0 A7: 0xffffffff7 A8: 0x00000000 A9: 0x00000000
A10: 0x000000ad A11: 0x00000000 A12: 0x800861de A13: 0x3ffbb010
A14: 0x00000003 A15: 0x00060a23 SAR: 0x00000020 理由: 0x00000007
EXCVADDR: 0x00000000000 f 6 LCOUNT: 0x00000000
ISR コンテキストで実行されるコア 0: EPC1: 0x4008a2e8 EPC2: 0x00000000 EPC3: 0x00000000 EPC4: 0x40008150

逆追跡: 0x4000814d: 0x3ffb0670 0x40082259: 0x3ffb0700 0x400833b9: 0x3ffb0720 0x400833e2: 0x3ffb0740 0x000 2e 5: 0x3 ffbb0a0 0x4008438d:0x3ffbb0c0 0x400830ed:0x3ffbb0e0 0x40083271:0x3ffbb110 0x400de4b1:0x3ffbb130 0x4 :0x3ff bb170 0 x 400de175:0x3ffbb1d0 0x400dccf2:0x3ffbb240 0x400dcedf:0x3ffbb2a0 0x400dcf47 :0x3ffbb2d0 0x400dbebf:0x3ffbb2f0 0x400dbed2:0x3ffbb310 0x400d757a:0x3ffbb3300300 a66:0x3ffbb380

ELFファイルSHA256: c278c3c874dd3748

再起動中...

この時点でトレースバックが指すコードチェックを開始できます。

addr2line xtensa-esp32- -pfiaC -e project.elf 0x400d3a66 0x400d770a 0x400d757a ...(the remaining addresses of the backtrace)

出力は次のとおりです。

0x400d3a66: root_task は $somePATH/build/../main/main.c:163 にあります。

0x400d770a: $somePATH/build/../main/init_app.c:122 で初期化中

0x400d757a: init_nvs_app は $somePATH/build/../main/init_app.c:47 にあります。

(インライン) init_nvs_app は /$somePATH/build/../main/init_app.c:34 にあります。

それは退屈。そのため、自動化する必要がありますが、シェルスクリプトの経験はあまりありません(Linuxに初めて触れます)。

これを達成する方法も何百万ものあります。経験豊富な人が「マスター瞑想エラー:」と「再起動...」の間のテキストを把握するのに役立ちますか?トレースバックからPC(プログラムカウンタ)アドレスを1行に分割し、SP(スタック)を無視する最善の方法は何ですか?ポインタ)(この特別な場合、SPアドレスは0x3ffで始まります)。 grep regexとawkでいくつか試しましたが、十分ではありません。

ベストアンサー1

sedバージョン:

sed -n -E -e '/^Backtrace:/ {s/Backtrace://; s/:0x3ff[^ ]* */ /g; p}' input.txt

これは、「Backtrace:」で始まらない行をすべて無視し、2つの検索規則と置換規則を使用して、出力を印刷する前に一致する行を変更します。

これs/:0x3ff[^ ]* */ /gは次に始まり、その後:0x3ffにゼロ個以上の空白以外の文字([^ ]*)が続き、その後にゼロ個以上の空白( *)が続くすべてのテキストを一致させ、見つかった一致を単一の空白文字に置き換えます。グローバル検索と置換(/g)なので影響を与えます。みんな最初の一致だけでなく、オンラインで見つけた一致です。

「Guru Meditation」と「Reboot」の操作を制限しようとしません。入力に「Backtrace:」で始まる他の行がない場合、または一度に1つの入力ファイルしか提供されていない場合は、この方法で十分です。

複数の実行で一定でない場合は、コロンと1つ以上の16進数が続く正規表現0x3ffに変更できます。0x例えば

s/:0x[0-9a-f]+//gi

この変更は、必要に応じてデフォルトのawkおよびPerlバージョンでも機能します。

awkバージョン:

awk -v SKIP=1 '/^Guru Meditation Error/ { SKIP=0 };
               /^Rebooting\.\.\./ { SKIP=1} ;
               SKIP==1 || ! /^Backtrace:/ { next };
               {
                   sub("^Backtrace:","");
                   gsub(":0x3ff[^ ]* *"," ");
                   print
               }
              ' input.txt

これは、「Guru Meditation」と「Rebooting」行の間にないすべての入力と、「Backtrace:」で始まらないすべての入力をスキップします。次に、修正された行を印刷する前にスキップsub()されていない行を修正するために、2つの検索と置換操作(および)を使用します。gsub()

パールバージョン:

perl -lne 'BEGIN {$SKIP=1};
           $SKIP=0 if (m/^Guru Meditation Error/);
           $SKIP=1 if (m/^Rebooting\.\.\./);
           next if ($SKIP || ! m/^Backtrace:/);
           s/Backtrace://;
           s/:0x3ff\H*\h*/ /g;
           print' input.txt

これは awk バージョンと同様に機能しますが、コードは awk と sed バージョンの間の交差のように見えます (perl は awk 様および sed 様構文などが可能です)。

最後の操作は、スペース(タブやスペースなど)だけでなく、Perl(非水平スペース文字)と(水平スペース文字)の一致をs//g使用するように変更されました。詳細については、「空白」セクションを参照して検索してください。\H\hman perlrecharclass

3つのバージョンすべての出力は同じです。

0x4000814d 0x40082259 0x400833b9 0x400833e2 0x40081e6a 0x4008a2e5 0x4008438d 0x400830ed 0x40083271 0x400de4b1 0x400dd525 0x400dd7c5 0x400de175 0x400dccf2 0x400dcedf 0x400dcf47 0x400dbebf 0x400dbed2 0x400d757a 0x400d770a 0x400d3a66 

3つのバージョンすべてが、標準入力またはコマンドラインの1つ以上のファイル名から入力を受け取ることができます。上記の例では使用しますinput.txt(例入力をコピーして貼り付けたテキストファイルです)。

どちらもstdoutとして出力するので、コマンドの置き換えに使用できます。例えば

addr2line xtensa-esp32- -pfiaC -e project.elf $(sed -n -E -e '/^Backtrace:/ {s/Backtrace://; s/:0x3ff[^ ]* */ /g; p}' input.txt)

おすすめ記事