Rubyやgit-gsubを使って正規表現で複数行を置換する

150個を超える *.tf をまとめて編集する方法を調べたので、備忘録としてまとめておく。

経緯

やりたかったこと

以下のようなコードが大量にあるとき、全てのファイルから指定のチームidを持つ team { ... } を削除したい。

resource "github_repository_collaborators" "foo" {
  repository = github_repository.foo.name
  team {
    permission = "push"
    team_id    = "rubyist"
  }
  team {
    permission = "admin"
    team_id    = "ruby-committers"
  }
}

ruby-jp に相談

Rubyが得意なのでRubyで置換する方法を調べていたが、うまくいかなかったので ruby-jp に相談した。

すると、何人かの方から回答を頂いた。

投稿した質問

Rubyでファイルの中身を置換する簡単な方法は何かあったりしないでしょうか?
ruby -e 'File.read("foo.txt").gsub(/def/, "!!").then { File.write("foo.txt", _1) }' みたいな処理を簡単に書けないものかなと。

回答1

Ruby-i -p を使う方法を教えて頂きました。

$ ruby -i -p -e '$_.gsub!(/def/, "!!")' foo.txt

これらのオプションは初めて知って勉強になった。

-i[extension] edit ARGV files in place (make backup if extension supplied)

-p assume loop like -n but print line also like sed

あと、 $_ も初めてみた。

docs.ruby-lang.org

ただ、これだと team { ... } のような複数行を処理できないため、別の方法が必要になった。

回答1-a

回答1 を参考に -i を使いつつ、複数行を取得して正規表現で置換することで目的は達成できた。

$ ruby -i -e 'puts readlines.join.gsub(/  team {[\s\w="\.\[\]]+(ruby-committers)[\s\w="\.\[\]]+}\n/, "")'

回答2

Ruby ではないですが、git-gsub を使う方法も教えて頂きました。

$ git gsub "(?s)team {[^{]+?ruby-committers.+?}" ""

正規表現もシンプルですし、 git-gsub は普段使いしやすそうなので、これも知ることができて勉強になった。

まとめ

ruby-jp に助けられたし、勉強になった。ありがとうございます。