$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

ある特定のパターンにヒットする次の行が特定のパターンだった時に削除するワンライナー

あるディレクトリ以下で特定のパターンにヒットする行を全て削除する - $shibayu36->blog;に引き続き、やり方を模索してみた。

たとえばgolangを使っていて、ある処理をt.Cleanupに寄せたので対応するdeferを全部消したい時がある。

// StartHogeHelperの中でt.Cleanupを使って自動でhogeHelper.Close()を呼ぶことにした
hogeHelper := StartHogeHelper(t)
// この行を消したい
defer hogeHelper.Close()

これはつまり「StartHogeHelperを呼んだ次の行でdeferを呼んでいたらdeferの行を削除する」と言い換えられる。もちろんこのやり方だと間違ったものも削除することもあるが、そこは手動で直すとして、ひとまず大多数を自動削除したい。

awkを使って実現する。また効率化のためgit grepを利用する。

git grep -l StartHogeHelper | xargs awk -i inplace '/StartHogeHelper/ {print; getline; if ($0 !~ /defer/) print; next} 1'
  • git grep -lを使ってStartHogeHelperを使っているファイル名を取得
  • xargsでファイル名を一つずつawkに渡す
  • awk -i inplaceでファイル自体をreplaceする
  • /StartHogeHelper/ {print; getline; if ($0 !~ /defer/) print; next} 1
    • StartHogeHelperにマッチしたら
    • まずその行をprint
    • getlineで次の行を取得
    • deferがあった時だけその行をprint。そうでなければその行を捨てる
    • 1を最後に使うとStartHogeHelperにマッチしない行はそのまま出力してくれる

こんな感じで一斉削除できて便利でした。