Perlの記述で「'」「"」などのクォーテーションではまった! その1 | to be continued ~とあるプログラマーの実験的開発日誌~

to be continued ~とあるプログラマーの実験的開発日誌~

WEBデザイナー兼プログラマーである管理人が日々のトラブル解決に向けて奮闘する開発日誌。

前回、JavaScriptが有効な場合のみポップアップのリンクを表示させる方法として
JavaScriptのdocument.writeでリンクタグを記述するやり方を紹介した。
記事では簡単に書いているが、実はどうしても上手くいかなくて半日ほど悩んだ。
もしかしたら同じようにはまる人がいるかも知れないので、
今回はその顛末について書いてみようと思う。


まず、何をしたかったかというと、CGIで動的なページを出力するのだが、
そこにJavaScriptが有効な場合のみ表示されるポップアップのリンクを表示させるのが目的である。
そこである変数(仮に「$contents」とする)にリンクタグを記述したJavaScriptのタグを格納する。
もう少しわかりやすく説明すると、

<script type="text/javascript">
<!--
document.write("ここにリンクタグが入る");
// -->
</script>

というJavaScriptの記述に

<a href="リンクアドレス" onclick="window.open(this.href, 'popwindow', 'width=500, height=500, menubar=no, toolbar=no, scrollbars=yes'); return false;">リンク先</a>

というリンクタグを記述して、
それを$contentsという変数に格納するのである。
ちなみにできるだけシンプルにするため、余分なエスケープ処理をする必要がない
ヒアドキュメントで行う。


何も考えずに記述すると、こんな感じ。

$contents =<<EOS;
<script type="text/javascript">
<!--
document.write("<a href="リンクアドレス" onclick="window.open(this.href, 'popwindow', 'width=500, height=500, menubar=no, toolbar=no, scrollbars=yes'); return false;">リンク先</a>");
// -->
</script>
EOS


当然ながらまったく動かない。理由は至極単純で、document.writeの表示部分は
「'」(シングルクォーテーション)もしくは「"」(ダブルクォーテーション)で囲まれた範囲であるのに
その内容にも「'」や「"」が含まれているため、範囲が特定できずにいるからだ。
まあ、スクリプトを書いていればこれはよく直面する問題なので、

この時点ではあまり気にしていなかった。

通常、クォーテーション内にクォーテーションがある場合の対処法は二つ。
一つは範囲を指定するクォーテーションと記述内容のクォーテーションをシングルとダブルに分けること。
つまり、範囲を「'」で囲っているなら内容の部分は「"」にしてやれば良い。
ただし、PerlやPHPの場合、「'」と「"」は同じようには使えないので注意が必要だ。
「'」の場合、記述内容はそのまま使われる。

つまり、変数などを使用していれば変数名がそのまま出力される。
「"」であれば置き換えられた値が出力される。
この点にだけ注意すればわかりやすい方法といえるだろう。
しかし、どちらも置き換えたい場合(当然その逆も)や

記述内容に「'」「"」が混在する時などはこの方法が使えない。
そこでもう一つの方法として、エスケープ処理を使う。
これは対象となる文字の前に「\」を付けることで、

本来特殊な意味を持つ記号をただの文字として扱うというものだ。
今回の例で言えば「範囲を指定する」という特殊な意味を持つ「"」を「\"」とすることで、
単なる文字とする(従って、最初と最後に付けるクォーテーションは範囲を指定させるので

エスケープさせてはいけない)。
というわけで、この二つの方法で修正してみる。
まず、リンクタグの「"」をそのまま使用できるようdocument.writeを囲うクォーテーションを「'」に変更。
これでリンクタグ内の「'」はそのまま使用できないので、エスケープ処理をしてやる。


修正した結果は次の通り。

$contents =<<EOS;
<script type="text/javascript">
<!--
document.write('<a href="リンクアドレス" onclick="window.open(this.href, \'popwindow\', \'width=500, height=500, menubar=no, toolbar=no, scrollbars=yes\'); return false;">リンク先</a>');
// -->
</script>
EOS


で、これで思い通りに動作するかというと、動かない・・・。
「'」と「"」を入れ替えたりしてみても結果は変わらず。
当然、これで解決したと思っていたのでここからはまる。
なぜ動かないか原因がわからん。
ちなみに出力したページのソースを見ると、

<script type="text/javascript">
<!--
document.write('<a href="リンクアドレス" onclick="window.open(this.href, 'popwindow\', 'width=500, height=500, menubar=no, toolbar=no, scrollbars=yes'); return false;">リンク先</a>');
// -->
</script>

となっていて問題はないように見える。


では、何が原因か?
勘のいい人ならお気づきだろう。
でも解答は次回に持ち越し。