はじめに
yq使えばいいじゃん、なのですが、環境によってインストールしたくない場合があります。でもyamlファイルの中身を書き換えたい。そんな時にsedを使えば解決できます。
今回は例としてハッシュ(キー: バリュー)のみの単純なデータ構造で構成するファイルを使用して説明していきたいと思います。尚、yamlファイルはハッシュのみならず、配列やネスト(入れ子)の構造も扱えます。そのような構造が入り混じっていても適宜指定する方法があるので、本記事をベースに応用していただけますと幸いです。
yamlファイルを作成する
👉手順1
key1: value1 key2: value2 key3: value3
yqコマンドでファイルの中身を書き換える方法
まず、従来のyqでファイルの中身を書き換える方法について確認します。
※$
はコマンド部分を表したものです。実際には入力しないでください。$
の無い部分は出力結果を表します。
yqコマンドでファイルの中身を書き換える
下記がコマンドの構文になります。
$ yq '[.キー=バリュー]' [ファイルパス]
👉手順2
- では、
key1
の値をChanged1
に変更してみます。
$ yq '.key1 = "Changed1"' test.yaml key1: Changed1 key2: value2 key3: value3
- key1の値が書き換わったものが出力されました。しかし、ファイルに出力していないので実際のファイルは書き変わっていません。
cat
コマンドでファイルの中身を確認できます。
$ cat test.yaml key1: value1 key2: value2 key3: value3
yqコマンドで得た値をファイルとして出力する。
下記のように入力します。
$ yq '[.キー=バリュー]' [ファイルパス] > [出力ファイルパス]
👉手順3
- では
key1
の値をChanged1
に変更し、変更したものを「changed.yaml」としてファイルに出力します。
$ yq '.key1 = "Changed1"' test.yaml > changed.yaml
- 「changed.yaml」の中身を
cat
コマンドで確認
$ cat changed.yaml key1: Changed1 key2: value2 key3: value3
書き変わっているのが確認できます。
続いては上記yq
コマンドで行ったyamlファイルの書き換え、ファイル出力をsed
コマンドを使って行う方法について説明します。先程の手順で作成された「changed.yaml」を削除してから次の手順に移ります。
$ rm changed.yaml
sedコマンドでファイルの中身を書き換える方法
先程説明したyqコマンドで行ったことをsedで同じように行います。
sedコマンドでファイルの中身を書き換える
下記がsedで値を書き換える際の基本的なコマンドの構文になります。
$ sed -e "s/[書き換え対象の文字列]/[書き換える値]/g" [書き換えるファイルのパス]
👉手順4
- では、
key1
の値をChanged1
に変更してみます。
$ sed -e "s/key1: value1/key1: Changed1/g" test.yaml key1: Changed1 key2: value2 key3: value3
- key1の値が書き換わったものが出力されました。しかしyqと同様に、ファイルに出力していないので実際のファイルは書き変わっていません。
cat
コマンドでファイルの中身を確認できます。
$ cat test.yaml key1: value1 key2: value2 key3: value3
sedコマンドで得た値をファイルとして出力する
先程と同様に下記のように入力します。
$ sed -e "s/[書き換え対象の文字列]/[書き換える値]/g" [書き換えるファイルのパス] > [出力ファイルパス]
👉手順5
- では
key1: value1
をkey1: Changed1
に変更し、変更したものを「changed.yaml」としてファイルに出力します。
$ sed -e "s/key1: value1/keyi: changei/g" test.yaml > changed.yaml
- 「changed.yaml」の中身を
cat
コマンドで確認
$ cat changed.yaml key1: Changed1 key2: value2 key3: value3
書き変わっているのが確認できます。
バリューの値が固定値では無い時は正規表現で書き換える!
前のsed例ではバリューの値が固定では無い時、分からない時は対応できません。yqの場合は「キー=~~」という形で記述できたので、同じような事をするためには、正規表現を使う事で解決できます。
下記が正規表現を使ってバリューの値が固定値では無い場合でも対応できるコマンドの構文になります。
$ sed -e "s/^[書き換え対象の文字列]:.*/[書き換えるキー]: [書き換えるバリュー]/g" [書き換えるファイルのパス] > [出力ファイルパス]
👉手順6
- では
key1
の値をChanged1
に変更し、変更したものを「changed.yaml」としてファイルに出力します。
$ sed -e "s/^key1:.*/key1: Changed1/g" test.yaml > changed.yaml
- 「changed.yaml」の中身を
cat
コマンドで確認
$ cat changed.yaml key1: Changed1 key2: value2 key3: value3
書き変わっているのがわかります。
因みにsedの-i
オプションを使えばファイルを上書きすることもできます。その場合は下記コマンドになります。
$ sed -i -e "s/^key1:.*/key1: Changed1/g" test.yaml
-e
コマンドはexpressionの略で続くものがスクリプト処理であることを明示的に表しています。s/○○/●●/g
がスクリプトにあたります。
正規表現「^
」、「.
」、「*
」について
使用した正規表現についてひとつずつ説明していきます。
^
は正規表現で「行頭」を表します。今回の例では、ネストされていないyamlファイルを用いましたので、キーは行頭から始まります。これを使わないと例えば「config_key1」、「hoge-key1」などの「key1」が含まれる文字列全てが対象となって思い通りの挙動にならない可能性があります。.
は正規表現で「任意の文字列」を表します。今回の例の場合は空白(スペース)を表します。今回の例では:
の次にスペースを挟むのがyamlの形式ですので、空白文字を判定する必要があります。*
は正規表現で「直前パターンの繰り返し」を表します今回の場合は文字列の繰り返しを表し、「v a l u e 1」を抽出します。
→合わせると「(行頭)key1:(空白)(文字列の繰り返し)」を「key1: Changed1」に書き換えるという意味になります。
終わりに
最後まで読んでいただきありがとうございました。yqが便利でyamlコマンドを使ってシェルスクリプトをガリガリ書いていたのですが、yqをインストールできない要件の環境で実行することになり、やむなくsedに変更する作業が発生しました。なかなかピンポイントで同じことをやっている人がいなかったので投稿に至りました。