正規表現が一致するまで下から行を抽出します。

正規表現が一致するまで下から行を抽出します。

この出力があります。

[root@linux ~]# cat /tmp/file.txt
virt-top time  11:25:14 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.0  0.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.0  0.0  95:44:07 instance-00000372
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372

2つのチャンクがあることがわかり、最後のチャンクを抽出したいです(最初のチャンクにCPUがすべて0の場合は問題ありません)。簡単に言えば、次の最後の行を抽出したいと思います(注:時には2つ以上のインスタンスがあります。 - *)そうでない場合は、「tail -n 2」を使用できます。

1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372

私はsed / awk / grepと可能なすべてを試しましたが、望む結果に近いものはありません。

ベストアンサー1

少し愚かな感じがしますが、次のようになります。

$ tac file.txt |sed -e '/^virt-top/q' |tac
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372

GNUtacリバースファイル(GNU以外の多くのシステムで利用可能tail -rsedで終わる最初の行まで選択してください。ヘッダーを追加または削除virt-topできます。sed 1,2dtail -n +3

またはawkから:

$ awk '/^virt-top/ { a = "" } { a = a $0 ORS } END {printf "%s", a}' file.txt 
virt-top time  11:25:17 Host foo.example.com x86_64 32/32CPU 1200MHz 65501MB
   ID S RDRQ WRRQ RXBY TXBY %CPU %MEM   TIME    NAME
    1 R    0    0    0    0  0.6 12.0  96:02:53 instance-0000036f
    2 R    0    0    0    0  0.2 12.0  95:44:08 instance-00000372

すべての行を変数として収集し、で始まる行からその変数を消去しますvirt-top

ファイルが非常に大きい場合、tac+sedソリューションはファイルの終わりだけを読み取る必要があるため、より高速ですが、awk+ソリューションはファイル全体を上から読みます。

おすすめ記事