あるプロジェクトで、環境変数が.env
ファイルに格納されており、その中の一つの環境変数が、独特のフォーマットで記述されており、それをパースする必要があった。
そのメモとしてブログを残しておく。
問題
.env
ファイルに格納された文字列がある。
FOO=BAR
SOME='{ aks_node_vm_size="Standard_L8s_v2", dns_prefix="staging-e", agent_count_min=1,agent_count_max=10, agent_count_enable_autoscale=true, kubernetes_version="1.14.7", cluster_name="some-aks", vnet_subnet_name="some-aks-subnet", gateway_name="some-gateway" }'
この状況で、cluster_name
の値だけを取得したい。
dotnenv ファイルを読み込んで環境変数にする
これは意外とややこしい。当初はgrep
を使ってやろうとしていたが、上記のような複雑な変数は上手く読めなかったりした。しかし簡単な方法があった。
set-o allexport;source$TEST_ENV_FILE_PATHset +o allexport;
ちなみに-o allexport
は全ての変数をexportする指定で、-a
でもよいようです。
ちなみに +o
の指定はオプションの無効化になります。つまり、AllExportを指定した状態でEnvファイルを読み込めばまずは、環境変数までもってこれます。
複雑な環境変数をパースする。
SOME='{ aks_node_vm_size="Standard_L8s_v2", dns_prefix="staging-engine", agent_count_min=1,agent_count_max=10, agent_count_enable_autoscale=true, kubernetes_version="1.14.7", cluster_name="some-aks", vnet_subnet_name="some-aks-subnet", gateway_name="some-gateway" }'
これのパースだが、最初はこんなコードを書いていた。できるねんけど、ダサさが漂っている。基本的にやってることは、IFSを変えて,
で分割して、
余計なダブルクオートや、変数名をカットという感じ。
#!/bin/bashOLDIFS=$IFSIFS=","pattern="^cluster_name="CLUSTER_NAME=""for kv in$SOMEKEY_VALUE=$(echo$kv | xargs)if[[$KEY_VALUE=~ $pattern]];then
CLUSTER_NAME=$(echo$KEY_VALUE | sed's/cluster_name=//')fi
done
echo$CLUSTER_NAME
これを何とかワンライナーで出来ないかと思い、Sedを調査した。Sedの置換のコマンドを使っている。
cluster_name=の直後で、空白、もしくは,
ではない文字列をヒットさせる。\( \)
は、ここで
ヒットした内容を後で参照できる。つまり、空白や,
が先ほどの文字列の区切りにでてくるので、次にそれがヒットするまでは( )
の中の内容になる。.*
は任意の文字列にヒットする。この内容(つまり、cluster_name=以降の文字列)を、\1
つまり、( )
の中でヒットした内容を置換する。つまりそれは、"some-aks" になるので、それのダブルクオートをxargsでとって終わり。
CLUSTER_NAME=$(echo$SOME | sed's/.*cluster_name=\([^ ,]*\).*/\1/' | xargs)echo$CLUSTER_NAME
xargs で、"" が取り除かれるのは、元々 xargsはデリミタで分割した文字を返すもの
xargsは、改行等で区切られた標準入力を読み込み、空白で区切られた1行の文字列へ加工し、それを引数として指定したコマンドへ渡して実行させる。
https://ja.wikipedia.org/wiki/Xargs
なので、デリミタが無い場合は、単純に、1行の文字列に加工するけど、""をストリップするのだろう。
部分抽出に関しては下記のブログを参考にしました。