はじめに
SSI(Server Side Include)を利用して、画面の表示をそこそこディープに制御する必要があった。
その際、後方参照を用いた手法に難儀した話である。
枯れた技術かもしれないが、目をつむってほしい。
環境
- Apache2.4
- httpd.conf には IncludesNoExec
後方参照という言葉について
正直はっきり理解できていないが、ここでは正規表現等を用いて条件マッチした際、特定の箇所を抜くときに利用する特殊変数(\$1、$2...)のことを指す。
$1がうまく機能しない?
さて、ハマった記述は以下の形である。
<!--#If expr="%{QUERY_STRING} =~ /age=([^&]+)/" -->
<!--#set var="age" value="$1" -->
<!--#Endif -->
期待する$1の返却値はクエリストリング内のage=に記載される数値だが、これで変数ageをechoすると(none)が返される。
Apacheの公式ドキュメントにサンプルとしてほぼ同一の記載があるのに、だ。
$0にはなにがある?
上記コードの\$1を\$0にしechoすると、age=数値
が表示される。
つまり、まったく後方参照が利用できないというわけではなさそうだ。
結論
以下の記述であれば、期待する値を取得できることが分かった。
<!--#If expr="%{QUERY_STRING} =~ /age=([^&]+)/" && $1 =~ /([^&]+)/" -->
<!--#set var="age" value="$0" -->
<!--#Endif -->
http://~~~/?age=123
123
読解してみると、If文に合致する箇所は数値の部分であり、
\$0は条件合致した内容をすべて表示するため、これで数値箇所のみを取り出せることが分かった。
なぜこうなるか(考察)
\$1以降の後方参照は、If文と同列でないと取り扱えないようである。
※濁した書き方なのは、正式な仕様がどこにも見つからないからだ。
調査にだいぶ時間がかかったのは、日本語のドキュメントで本問題を取り扱ったものが見当たらなかったからである。
(stackoverflow には似たような質問が散見された)
何らかの事由で、SSIを利用し条件マッチによる制御を行う必要がある諸兄の一助になれば幸いである。
補足
Apache2.2では、If文と同列でなくとも後方参照は動作するようである。
そもそもApache2.4になってからSSIにおける変数の記述や正規表現マッチの書き方が微妙に変わっており、
日本語のナレッジも少ない為、ディープに利用している諸兄は是非発信していって欲しい。