zaki work log

作業ログやら生活ログやらなんやら

[Linux] AWKで正規表現置換

コマンドの出力を正規表現使って文字列置換するならsedを使うことは多いけど、行ごとに処理するだけで「前の行の情報」などどうだったかとかの状態を維持する仕組みが(たぶん)ないので、例えば「特定の文字列パターンを正規表現で処理しつつ連番を振る」がsedは(たぶん)できない。(連番の部分)

この要件ならawkを使えばできる。

お題:ps auxの結果の行頭に行番号を3桁ゼロ詰めで追加

お題そのものは全く実用的ではないけど、変数使った正規表現置換という例。
コマンドは以下。

ps aux | awk '{sub(/^/, sprintf("%03d: ", ++i)); print}'

AWKsub(regexp, replace)正規表現置換するので、/^/で行頭をsprintf("%03d: ", ++i)で3桁ゼロ埋めの連番に置換し、最後にprintする、という寸法。

出力は以下の通り。

$ ps aux | awk '{sub(/^/, sprintf("%03d: ", ++i)); print}'
001: USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
002: root           1  0.0  0.1  47584 14500 ?        Ss    5月07   0:16 /usr/lib/systemd/systemd --system --deserialize=167 rhgb
003: root           2  0.0  0.0      0     0 ?        S     5月07   0:00 [kthreadd]
004: root           3  0.0  0.0      0     0 ?        S     5月07   0:00 [pool_workqueue_release]
005: root           4  0.0  0.0      0     0 ?        I<    5月07   0:00 [kworker/R-kvfree_rcu_reclaim]

[snip]

Perlの場合

最初はsedでできるかと思ってコマンドライン書き始めたらうまくいかなかったのでawkを試したが、少し込み入った正規表現置換するならperlの方がすっきり書けるかも。

同じお題を処理するなら以下。

ps aux | perl -pe 's/^/sprintf("%03d: ", ++$i)/e'

-pを付けるとprintが不要になるので少し短く書ける。


補足

  • AWK」「Perl」:言語名
  • awk perl:コマンド名