egrep マッチする部分を抽出する

smartyのテンプレートファイルから、変数名のリストを抽出したかった。
${ と } で囲まれた変数名を、重複を省いてリストにしたい。一行に複数の変数名がある場合があることにも注意すべきだ。

たとえばこんなファイルがあるとする。

--code--
{$apple}
--code--{$apple}--code--{$chocolate}--code--{$banana}--code--
--code--{$banana}--code--{$chocolate}--code--

これに埋め込まれている変数名を、

apple
banana
chocolate

のように抜き出したい。

とりあえずegrep '{\$.+}' sample.tplしてみる。

{$apple}
--code--{$apple}--code--{$chocolate}--code--{$banana}--code--
--code--{$banana}--code--{$chocolate}--code--

そうだね。行ごと出力されるね。-o(--only-matching)オプションで、マッチ部分のみ出力する。

$ egrep -o '{\$.+}' sample.tpl
{$apple}
{$apple}--code--{$chocolate}--code--{$banana}
{$banana}--code--{$chocolate}

greedy matchするね。?をつけてnon-greedy matchにする。

$ egrep -o '{\$.+?}' sample.tpl
{$apple}
{$apple}
{$chocolate}
{$banana}
{$banana}
{$chocolate}

よし。これをソートしてユニークにする。

$ egrep -o '{\$.+?}' sample.tpl | sort | uniq
{$apple}
{$banana}
{$chocolate}

まあオーケー。でも、{$ と } がないほうがいい。

$ egrep -o '{\$(.+?)}' tes.txt | sort | uniq | sed 's/{\$//' | sed 's/}//'
apple
banana
chocolate

よし。
でももっといい方法がいくらでもあるはずだ。

2016/8/25追記: これでも可能。

$ egrep -o '{\$.+?}' tes.txt | sort | uniq | tr -d '${}'