sedでiniファイルをパースする方法とその解説


たとえば以下のようなini形式ファイルがあり、ここから[example.jp]セクションの内容だけ抜き出したい場合のsedでの実現方法を紹介します。

iniファイル例

data.ini
[example.org]
foo=/home/foo

[example.jp]
foo=/home/foo
bar=/home/bar
baz=/home/baz

[example.com]
alice=/Users/alice
bob=/Users/bob
chary=/Users/chary

bashスクリプト

ワンライナーにもできますが、正規表現の部分を分かりやすくするためにシェルスクリプトにしました。

extract-inisection
#!/bin/bash

# 抽出するセクション名
#  正規表現内で使用するため、ピリオドをエスケープ
SECTION=`sed -re 's|\.|\\.|g' <<<"$1"`

# セクション開始検索用正規表現
SECTION_PAT="^[ \t]*\[${SECTION}\][ \t]*$"

# セクション終了検索用正規表現
SECTION_END_PAT='^[ \t]*\[[^]]+\][ \t]*$'

sed -nre "/${SECTION_PAT}/{p;:LOOP;n;/${SECTION_END_PAT}/Q;p;b LOOP}"

実行例

$ ./extrat-inisection example.jp < data.ini
[example.jp]
foo=/home/foo
bar=/home/bar
baz=/home/baz

解説

sedのスクリプト部分をコマンド毎に解説すると以下のようになります。sedに-nオプションをつけて実行しているので、パターンスペースに読み込んだ行はpコマンドを実行しない限り出力されません。

/${SECTION_PAT}/ {        # パターンスペースの内容がセクション開始正規表現にマッチしたらブロックの内容を実行
  p;                      # パターンスペースの内容を出力(セクション名を出力するためなので、これを無くせばセクション内部だけ取得できる)
  :LOOP;                  # ループ用のラベル
  n;                      # 次の1行をパターンスペースに読み込む
  /${SECTION_END_PAT}/Q;  # パターンスペースの内容がセクション終了正規表現にマッチしたらスクリプトを終了
  p;                      # パターンスペースの内容を出力
  b LOOP                  # 「LOOP」ラベルに戻る
}

(おまけ)セクション名の列挙

こちらはわりと簡単。

$ sed -nre 's|^[ \t]*\[([^]]+)\][ \t]*$|\1|p' < data.ini
example.org
example.jp
example.com