テキストをある形式から別の形式に変換する必要があることがよくあります。一般的な状況は、いくつかの情報を含むログファイルがあり、その情報のサブセットを見つけて非常に具体的な方法でフォーマットすることです。
今、すべての「レコード」が同じ行にある場合、操作は比較的簡単です。
grep
オプションで、関心のある行のみを一致させるために使用できます。sed
目的のフィールドを一致させ、キャプチャし、必要に応じてフォーマットされた結果を出力するために使用されます。
唯一の小さな問題はみんな行なので、sed
その行は破棄され、目的の出力のみが印刷されます。しかし、それほど難しくありません。
フィールドキャプチャの問題が十分簡単であればcut
十分かもしれませんawk
。
今実際の質問は次のとおりです。必要なフィールドが複数行にまたがっている場合はどうなりますか?
たとえば、ある人がいるとしましょう。
stat * >LOG.TXT
いいですね。今、私LOG.TXT
たちが望むすべての情報を含むファイルができました。しかし、次のようになります。
File: 'src.7z'
Size: 269430 Blocks: 528 IO Block: 4096 regular file
Device: 801h/2049d Inode: 799155 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-07-02 09:01:09.269292914 +0100
Modify: 2020-07-02 09:00:53.237293629 +0100
Change: 2020-07-02 09:00:53.237293629 +0100
Birth: -
おそらく、私たちは少し似ているように見えるものを生成したいと思うかもしれません。
VerifyFile("src.7z", 269430, 0644);
今、正しい方法そのための最初のステップは、stat
このように出力を要求することです!一般的に言えば、いつも実際には、フランケンシュタインのテキストを作成しようとするよりも、ソースプログラムで起動したい形式を生成する方がよいでしょう。残念ながら、人生はいつもそれほど単純ではありません。ログファイルがあり、接続イベントと切断イベントをリンクしたい場合や、ファイルリストがあり、各.c
ファイルを一致する.o
ファイルに関連付けたい場合があります。理由が何であれ、最終的にはテキスト修正作業に直面することになります。
それでは、この問題を解決するための最良の方法は何ですか?複数の個別の行からフィールドを収集し、同じ行にマージしながらレコードを別々に保持するにはどうすればよいですか? (つまり入れないでください。すべて巨大な行には同じ記録。 )
この種のタスクを実行する一般的な方法はありません。いくつかの考え:
grep
正規表現に一致する部分のみ抽出を使用して、目的のフィールドを抽出できます。しかし、抽出する方法はありません。みんな興味深いフィールドを複数回実行しないと、grep
フィールド間の相対的な順序が壊れる可能性があります。sed
一致するビットだけを抽出することはより困難になりますが、フィールドを同じ相対順序で維持できます。今何とか同じ行にフィールドを収集する必要があります。awk
フィールドとレコードの概念があります。私信じる正規表現の一致を実行できます。 (本当に分からないawk
。)おそらくそれがこの問題を解決する方法ではないでしょうか?かなり複雑に見えますが。- Pythonで何かできますか?一般的にインストールされているようです。正規表現機能があるかどうかわかりません。
通常私は次のことを思い出します。働くしかし、読みやすくメンテナンスが容易ではありませんでした。もっと簡単な方法があったらと思います。
答え1
どちらもここにawk
適していますpython
。どちらも連想配列(または辞書)をサポートし、両方とも正規表現が組み込まれています。
おそらくこれを処理するいくつかの一般的な方法がありますが、私は利用可能な実際の入出力例に基づいて最適化する傾向があります。これがstat
解決された問題ですawk
。
$ cat kv.awk
/File:/ {
f = $2
}
/Size:/ {
info[f] = $2
}
/Access.*Uid/ {
gsub(/\(|\/.*/, "", $2)
info[f] = info[f] OFS $2
}
END {
for (k in info) {
print "VerifyFile(\"" k "\"", info[k] ");"
}
}
ファイル名は次のように使用されます。鍵関連するすべてを集めてください。最後に、必要なすべての形式で結果を表示できます。GNU awk
多次元配列もサポートされます。
実行例は次のとおりです。
$ stat ip.txt test.txt > file.txt
$ awk -v OFS=', ' -f kv.awk file.txt
VerifyFile("'test.txt'", 254, 0664);
VerifyFile("'ip.txt'", 301, 0664);
勉強することをawk
お勧めしますhttps://www.gnu.org/software/gawk/manual/gawk.html他の実装に関する詳細が取り上げGNU awk
られ、言及されています。