同じ行に入れ子になった区切り文字を含むテキストファイルを解析します。

同じ行に入れ子になった区切り文字を含むテキストファイルを解析します。

btrfsが.btrfsというファイルに配置するbtrfsクリーンアップ統計を解析したいと思います/var/lib/btrfs/scrub.status.<uuid>。ファイルは実際にはキーと値のペアで構成されています。ここで、キーと値はセミコロンで区切られ、タプルはパイプ("|")文字で区切られます。

scrub status:1
b5872f47-c87e-47ac-b036-4f2725cf6dc6:1|data_extents_scrubbed:4996799|tree_extents_scrubbed:1436139|data_bytes_scrubbed:156663988224|tree_bytes_scrubbed:23529701376|read_errors:0|csum_errors:0|verify_errors:0|no_csum:733729|csum_discards:0|super_errors:0|malloc_errors:0|uncorrectable_errors:0|corrected_errors:0|last_physical:202959224832|t_start:1597847400|t_resumed:0|duration:67|canceled:0|finished:1

最後に、たとえば、各キーと値のペアを別々の行にエクスポートしたいと思います(これはPrometheus指標として使用されます)。

scrub status 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
[...]

私はsedこの入れ子になった解析を/accomplishing試してみましたが、awkこれまで失敗しました。

これを達成する方法についてのアドバイスをいただきありがとうございます!

答え1

  • すべてのsed:

    sed 's/:/ /g;s/|/\
    /g' file
    
  • GNU sed:

    sed 's/:/ /g;s/|/\n/g' file
    

ここでは、:スペース|と改行文字ですべてを変更します。

awkを使用すると、レコード区切り文字をパイプ文字に設定してから:スペースに置き換えることができます。

awk 'BEGIN{RS="|"}{gsub(":"," ");print}' file

答え2

複数文字RSにGNU awkを使用する:

$ awk -v RS='[|]|\n$' -F':' '{$1=$1}1' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

|また、上記のソリューションはRSを。

答え3

努力する:

$ awk -F'|' '{for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}' file
scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376

仕組み:

  • -F'|'フィールド区切り記号をに設定します|

  • {for (i=1;i<=NF;i++) {sub(/:/, " ", $i); print $i}}各フィールドを繰り返し、スペースを置き換えて:フィールドを印刷します。

答え4

trこれが文字を変換する最速の方法ではありませんか?

$ <file tr ':|' ' \n'

scrub status 1
b5872f47-c87e-47ac-b036-4f2725cf6dc6 1
data_extents_scrubbed 4996799
tree_extents_scrubbed 1436139
data_bytes_scrubbed 156663988224
tree_bytes_scrubbed 23529701376
read_errors 0
csum_errors 0
verify_errors 0
no_csum 733729
csum_discards 0
super_errors 0
malloc_errors 0
uncorrectable_errors 0
corrected_errors 0
last_physical 202959224832
t_start 1597847400
t_resumed 0
duration 67
canceled 0
finished 1

もちろん、tr1バイト文字でのみ機能します。これは:との問題ではありません|

sed (マルチバイト文字 (GNU/ATT) 使用可能) と同等の機能は次のとおりです。

<file sed 'y/:|/ \n/'

関連情報