冬言響 / 日記

アメコミとか映画とか音楽とか猫とか単車とか自転車とか革とか銀とかジーンズとかブーツとか今日喰ったものとか。

RSS2.0

(無題)

内容が HTML ソースコードである文字列 $strBody の中に Google 検索結果やら Wikipedia やらへのリンクで日本語を含む URI を属性値として持つ href 属性があった場合、その部分だけエンコードしたくて

$strBody = ereg_replace("href="([-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)([^"]+)"", "href="\1" . rawurlencode("\2") . """, $strBody);

とかやってみたのだけど意図通りの結果が得られない。ereg_replace() 内で \2 を引数として別の関数に投げてやってもちゃんと受け取ってくれないらしい。受け取ってくれても良いのに。ぐぐってみると他にも同じようなことしようとしてハマってる人がそこそこ居る様子。んで、以下ここ数日悩んで捻り出してみた俺的解答。

//二重引用符を区切り文字にしてブった斬って配列に格納する
$aryUrlEncode = split(""", $strBody);
//添字が奇数の配列要素は属性値、0 及び偶数のものはそれ以外なので、1 つ飛ばしで見ていく
for($i = 0; $i < count($aryUrlEncode); $i += 2)
	{
	//「href=」で終わる配列要素があればその次が href 属性値
	if(ereg("href=$", $aryUrlEncode[$i]))
		{
		//先ず UTF-8 に変換
		$aryUrlEncode[$i + 1] = mb_convert_encoding($aryUrlEncode[$i + 1], "utf-8", "Shift_JIS");
		//で、エンコード
		$aryUrlEncode[$i + 1] = rawurlencode($aryUrlEncode[$i + 1]);
		//このままだと「:」とか「/」とか全部エンコードされてるのでそのままじゃマズいものを一つひとつ元に戻す
		//なにかもっとシンプルかつエレガントに纏める手段があるに違いない
		$aryUrlEncode[$i + 1] = str_replace("%21", "!", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%7E", "~", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%2A", "*", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%28", "(", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%29", ")", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%3B", ";", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%2F", "/", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%3F", "?", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%3A", ":", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%40", "@", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%26", "&", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%3D", "=", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%24", "$", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%2C", ",", $aryUrlEncode[$i + 1]);
		$aryUrlEncode[$i + 1] = str_replace("%23", "#", $aryUrlEncode[$i + 1]);
		//「%」は最後(←重要 たぶん)
		$aryUrlEncode[$i + 1] = str_replace("%25", "%", $aryUrlEncode[$i + 1]);
		}
	}
//終わったらまた二重引用符を区切り文字として結合して元の変数に叩き込む
$strBody = join(""", $aryUrlEncode);

どうなんだろうなあ。まあ動いたから良いか。

ちょっといろいろ追記したりしてたら無駄に長いうえに収拾付かなくなったので過程を飛ばして結論だけにして書き直し。まあ、どうでも良いね。

preg_replace("/href="([-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)([^"]+)"/e", ""href=\"$1" . rawurlencode("$2") . "\""", $strBody); でできそう。

おー。あざーっす。てか preg_replace 便利ー。