カンマ区切りの文字列をプラグインなしで配列のようにループで取り出すTips

Movable Type でテンプレートを書いているとき、カンマ区切りの文字列があって、これを配列にしてループさせたいってことは多々あるかと思います。

そんな時は、荒木さんの Split プラグイン(小粋空間)を使ったりしますが、プラグインを使えない環境もあるかもしれません。

そこで、今回はプラグインを使わないで、カンマ区切りの文字列を配列のようにループする方法を紹介します。

完成したコード

<$mt:SetVar name="favorite" value="バッジョ,ジーコ,クライフ,ピルロ,ストイコビッチ,グアルディオラ"$>
<$mt:Var name="favorite" regex_replace="/[^,]/g","" cat="," count_characters="1" setvar="length"$>

<mt:For var="i" from="1" to="$length">
<mt:If name="__first__"><ul></mt:If>
<$mt:Var name="favorite" regex_replace="/^([^,]+).*/","$1" setvar="value"$>
<$mt:Var name="favorite" regex_replace="/^([^,]+,?)(.*)/","$2" setvar="favorite"$>
<li><$mt:Var name="value"$></li>
<mt:If name="__last__"></ul></mt:If>
</mt:For>

解説

まず、次のようなカンマ区切りの文字列を変数 favorite に入れておきます(変数名はご自由に)。

<$mt:SetVar name="favorite" value="バッジョ,ジーコ,クライフ,ピルロ,ストイコビッチ,グアルディオラ"$>

次に、このカンマ区切りの文字列の要素数を算出して、変数 length にセットします。

<$mt:Var name="favorite" regex_replace="/[^,]/g","" cat="," count_characters="1" setvar="length"$>

ここでの処理は次の順序で行っています。

  1. 区切り文字以外の文字([^,])を正規表現ですべて削除( regex_replace="/[^,]/g","" )
  2. 区切り文字を1つ追加( cat="," )
  3. その文字数をカウント( count_characters="1" )
  4. 変数 length にセット

次に、要素の数だけループする MTFor を用意します。

<mt:For var="i" from="1" to="$length">

</mt:For>

MTFor の中で、カンマ区切りの文字列の要素を一つずつ取り出していきます。

<mt:For var="i" from="1" to="$length">
<$mt:Var name="favorite" regex_replace="/^([^,]+).*/","$1" setvar="value"$>
<$mt:Var name="favorite" regex_replace="/^([^,]+,?)(.*)/","$2" setvar="favorite"$>
</mt:For>

ここでの処理は次の通りです。

  1. 2行目で行頭から「カンマ以外の文字グループ」 ^([^,]+) と「それ以降の文字」 .* とに分けてマッチさせ、最初の文字グループ $1 だけに置換しています。
    これで最初の要素だけを取り出せるので、その結果を変数 value にセットします。
  2. 3行目で行頭から「カンマ以外の文字とカンマの文字グループ」 ^([^,]+,?) と「それ以降の文字グループ」 (.*) とに分けてマッチさせ、後ろの文字グループ $2 だけに置換しています。カンマの後の ? は、最終要素の場合はカンマがないので、それへの対応です。
    これで最初の要素を除いたものを取り出せるので、その結果で変数 favorite を上書きします。 

なお、ダイナミックパブリッシングの場合は、置換文字列の部分 $1 を \$1 のようにエスケープします。

あとは、ループ内で、この変数 value を使って要素を出力すれば OK です。以下では、リストで出力しています。

<mt:For var="i" from="1" to="$length">
<mt:If name="__first__"><ul></mt:If>
<$mt:Var name="favorite" regex_replace="/^([^,]+).*/","$1" setvar="value"$>
<$mt:Var name="favorite" regex_replace="/^([^,]+,?)(.*)/","$2" setvar="favorite"$>
<li><$mt:Var name="value"$></li>
<mt:If name="__last__"></ul></mt:If>
</mt:For>

その他

配列に入れて再利用する

再利用性も考えて、以下のように、一度本当に配列にセットして、それをループで出力するという手もありますね。

<mt:For var="i" from="1" to="$length">
<$mt:Var name="favorite" regex_replace="/^([^,]+).*/","$1" setvar="value"$>
<$mt:Var name="favorite" regex_replace="/^([^,]+,?)(.*)/","$2" setvar="favorite"$>
<$mt:SetVar name="favorite_array" function="push" value="$value"$>
</mt:For>

<mt:Loop name="favorite_array">
<mt:If name="__first__"><ul></mt:If>
<li><$mt:Var name="__value__"$></li>
<mt:If name="__last__"></ul></mt:If>
</mt:Loop>

区切り文字がカンマ以外の場合

例えば区切り文字が「 AND 」(半角スペースAND半角スペース)のような場合は、最初に区切り文字を何かしらの1文字に置換して、それから同様にやればOKです。

以下では、「 AND 」を「@」に置換してから作業している例です。

<$mt:SetVar name="favorite" value="バッジョ AND ジーコ AND クライフ AND ピルロ AND ストイコビッチ AND グアルディオラ"$>
<$mt:Var name="favorite" regex_replace="/ AND /g","@" setvar="favorite"$>
<$mt:Var name="favorite" regex_replace="/[^@]/g","" cat="@" count_characters="1" setvar="length"$>

<mt:For var="i" from="1" to="$length">
<mt:If name="__first__"><ul></mt:If>
<$mt:Var name="favorite" regex_replace="/^([^@]+).*/","$1" setvar="value"$>
<$mt:Var name="favorite" regex_replace="/^([^@]+@?)(.*)/","$2" setvar="favorite"$>
<li><$mt:Var name="value"$></li>
<mt:If name="__last__"></ul></mt:If>
</mt:For>

以上です。

  • このエントリーをはてなブックマークに追加
Just a second...