apache httpd 2.4.2 の mod_sed の続きです。前回提示した例が動作しなかった原因を探ってみました。
まず分岐が正しく動作するかどうかを試してみます。
sed の分岐は、
b ラベル の通常の分岐と、
t ラベル の条件分岐です。
そこで、httpd-sed-scripts.conf を以下のようにします。
・最初の b コマンドで loop1 へ分岐し、
・行内に bad の文字があったら、good に変換して、
・t コマンドによって loop2 へ分岐します。
・badの文字が無ければそのままサイクルを終了して次の行へ行きます。
・loop2 へ分岐した場合は、good line を GOOD bad LINE に変えて、
・ラベルなし b コマンドでサイクルを終了して次の行へ行きます。
これによって、b,t コマンドが正しく動作しているかを調べるのがねらいです。早速、htmlファイルの次の部分を変換させます。
(例1)
First line<br>
good line<br>
bad line<br>
Last line<br>
結果は次のとおりです。
First line<br>
good line<br>
GOOD bad LINE<br>
Last line<br>
t コマンドの分岐で戻る動作や、b コマンドの終了動作もうまくいっています。
実は、b にアドレスを付けると、分岐先のラベルが無い場合でもサイクルを終了しないようですのでご注意ください。それで、以降の設定では、アドレス付きの b コマンドは必ずラベルを指定してあります。
次にアドレスを見てみます。! が使えないことは分かりましたので、以下を試してみます。
(以降は OutputSed のところのみ示します。)
OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "s/^.*$/IN &/"
OutputSed ":next"
OutputSed "}"
htmlファイルのこの部分を変換してみます。
結果は次のとおりです。
これもうまく動作しています。
最後に s コマンドの気になるところを試します。
OutputSed "s/\(One\)\(Two\)\(Three\)/¥3¥2¥1/"
OutputSed "/^Three/ s/^.*$/\n&\n/"
残念ながら以下の行が、
OneTwoThree
正しく変換されません。改行文字 \n が無視されて n とみなされます。
nThreeTwoOnen
どうやら、s/regexp/replacement/flags において、「replacement」の \n は認識されず n となり、「regexp」 の \n は認識されるようで、
OutputSed "N"
OutputSed "s/\(.*\)\n\(.*\)/¥1@¥2/"
は、2つの行が @ をはさんで1行として変換されます。
そこで改行文字は諦めて、@ 文字を使ってうまく動作しなかった sed スクリプトを修正してみます。
OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "/^$/ b next"
OutputSed "/^.$/ b next"
OutputSed "s/^.*$/@&@/"
OutputSed "t loop"
OutputSed ":loop"
OutputSed "s/\(@.\)\(.*\)\(.@\)/¥3¥2¥1/"
OutputSed "t loop"
OutputSed "s/@//g"
OutputSed "s/^\(.*[^ ]\)\( *\)$/¥2¥1/"
OutputSed ":next"
OutputSed "}"
(例2)は以下のようになり、何とかうまくいきました。
OutputSed修正後に動作確認を行う際には、
# touch /usr/local/httpd242/htdocs/sed/*
を忘れないようにしましょう。
というわけで、mod_sed には多少の問題点がありますが、Experimental ですし、たいていのものは出来るので、積極的に利用したいと思います。それに今回調べたことで、sed コマンドの奥深さが改めて分かったので、そちらも得した気分です。
(行間が無駄に開いている部分がありますが、gooブログの仕様です。)
まず分岐が正しく動作するかどうかを試してみます。
sed の分岐は、
b ラベル の通常の分岐と、
t ラベル の条件分岐です。
そこで、httpd-sed-scripts.conf を以下のようにします。
<Directory "/usr/local/httpd242/htdocs/sed"> AddOutputFilter Sed html OutputSed "b loop1" OutputSed ":loop2" OutputSed "s/good line/GOOD bad LINE/" OutputSed "b" OutputSed ":loop1" OutputSed "s/bad/good/" OutputSed "t loop2" </Directory>
・最初の b コマンドで loop1 へ分岐し、
・行内に bad の文字があったら、good に変換して、
・t コマンドによって loop2 へ分岐します。
・badの文字が無ければそのままサイクルを終了して次の行へ行きます。
・loop2 へ分岐した場合は、good line を GOOD bad LINE に変えて、
・ラベルなし b コマンドでサイクルを終了して次の行へ行きます。
これによって、b,t コマンドが正しく動作しているかを調べるのがねらいです。早速、htmlファイルの次の部分を変換させます。
(例1)
First line<br>
good line<br>
bad line<br>
Last line<br>
結果は次のとおりです。
First line<br>
good line<br>
GOOD bad LINE<br>
Last line<br>
t コマンドの分岐で戻る動作や、b コマンドの終了動作もうまくいっています。
実は、b にアドレスを付けると、分岐先のラベルが無い場合でもサイクルを終了しないようですのでご注意ください。それで、以降の設定では、アドレス付きの b コマンドは必ずラベルを指定してあります。
次にアドレスを見てみます。! が使えないことは分かりましたので、以下を試してみます。
(以降は OutputSed のところのみ示します。)
OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "s/^.*$/IN &/"
OutputSed ":next"
OutputSed "}"
htmlファイルのこの部分を変換してみます。
(例2)
First line<br>
<pre>
good line
</pre>
2nd line<br>
<pre>
good line
bad line
</pre>
Last line<br>
結果は次のとおりです。
First line<br>
<pre>
IN good line
</pre>
2nd line<br>
<pre>
IN good line
IN bad line
</pre>
Last line<br>
これもうまく動作しています。
最後に s コマンドの気になるところを試します。
OutputSed "s/\(One\)\(Two\)\(Three\)/¥3¥2¥1/"
OutputSed "/^Three/ s/^.*$/\n&\n/"
残念ながら以下の行が、
OneTwoThree
正しく変換されません。改行文字 \n が無視されて n とみなされます。
nThreeTwoOnen
どうやら、s/regexp/replacement/flags において、「replacement」の \n は認識されず n となり、「regexp」 の \n は認識されるようで、
OutputSed "N"
OutputSed "s/\(.*\)\n\(.*\)/¥1@¥2/"
は、2つの行が @ をはさんで1行として変換されます。
そこで改行文字は諦めて、@ 文字を使ってうまく動作しなかった sed スクリプトを修正してみます。
OutputSed "/<pre>/,/<¥/pre>/ {"
OutputSed "/<pre>/ b next"
OutputSed "/<¥/pre>/ b next"
OutputSed "/^$/ b next"
OutputSed "/^.$/ b next"
OutputSed "s/^.*$/@&@/"
OutputSed "t loop"
OutputSed ":loop"
OutputSed "s/\(@.\)\(.*\)\(.@\)/¥3¥2¥1/"
OutputSed "t loop"
OutputSed "s/@//g"
OutputSed "s/^\(.*[^ ]\)\( *\)$/¥2¥1/"
OutputSed ":next"
OutputSed "}"
(例2)は以下のようになり、何とかうまくいきました。
First line<br>
<pre>
enil doog
</pre>
2nd line<br>
<pre>
enil doog
enil dab
</pre>
Last line<br>
OutputSed修正後に動作確認を行う際には、
# touch /usr/local/httpd242/htdocs/sed/*
を忘れないようにしましょう。
というわけで、mod_sed には多少の問題点がありますが、Experimental ですし、たいていのものは出来るので、積極的に利用したいと思います。それに今回調べたことで、sed コマンドの奥深さが改めて分かったので、そちらも得した気分です。
(行間が無駄に開いている部分がありますが、gooブログの仕様です。)