* [PCRE] AutoLink用の正規表現: スペースや#記号が含まれていると 'x'(PCRE_EXTENDED) をつけている場合に挙動が変わる [#h13096e7]

-ページ: BugTrack
-投稿者: [[morikawa]]
-優先順位: 低
-状態: 完了
-カテゴリー: 本体バグ
-投稿日: 2003-12-08 (月) 09:29:22
-バージョン: 

#contents

** 修正 [#tcb7de21]

AutoLink用の正規表現について、
「正規表現の中で空白やコメント文を使用できるようにする」ためのオプション 'x'(PCRE_EXTENDED) を使用しているため、それらを適切にエスケープしないとうまく動作しないケースがある事がわかりました。

(1.4.3)
- [[cvs:func.php]](r1.57-1.58) -- 半角スペースについて別途エスケープする

(1.4.8)
- [[cvs:lib/func.php]] (1.95, 1.98, 1.99) -- white space と # についてエスケープする


** [1.4.3] ページ名が英数字で間にスペースがあると、autolink でマッチしない  [#hb97b30d]
autolink.dat のスペースをエスケープしたらOKそうでした。

autolink.dat
 ...|InterWikiテクニカル|Wen Jiabao|ヘルプ|整形ルール|日本語)
 ...|InterWikiテクニカル|Wen\ Jiabao|ヘルプ|整形ルール|日本語)

----
-PCRE_EXTENDED(エスケープするか 文字クラスの内部にある場合を除き、 パターンの空白文字は完全に無視する)を指定しているので、空白もエスケープする必要がありました。preg_quoteには追加のエスケープ文字がひとつしか指定できないので、str_replace(' ','\\ ',...)を通すようにしました。 -- [[ぱんだ]] &new{2003-12-10 (水) 09:42:34};
-cvsに投入しました。[[cvs:func.php]](v1.4:r1.57) func.phpを差し替えた後、適当なページを更新してautolink.datを再構築してください。 -- [[ぱんだ]] &new{2003-12-10 (水) 09:42:34};
--[[v1.4:r1.57]]で、とりあえずページ名が英数字で間にスペースがある場合に関してはOKそうです。 -- [[morikawa]] &new{2003-12-11 (木) 11:30:26};
-v1.4:r1.57導入すると''「ほげ」''とか''ほげ・げほ''とかがAutoLinkかからないような感じですがCVS難民なだけでしょうか。ダウングレードで元に戻りました。 -- [[たらこせる]] &new{2003-12-10 (水) 11:11:35};
-たらこせるさんと同じく、v1.4:r1.57導入で一部のページがAutoLinkに掛からなくなりました。1.56に戻すと直ります。どのページ名がAutoLinkに掛からないかを挙げれば解決に役立つでしょうか? -- [[司書]] &new{2003-12-14 (日) 01:59:11};
-v1.4:r1.57での変更点(557行目)にtypoがあります。そのせいで生成する正規表現が文字化けしてAutoLinkがおかしくなります。 -- [[ようか]] &new{2004-01-30 (金) 23:48:11};
 -$result .= str_replace(' ','\\ ',preg_quote(substr($pages[$i],$pos),'/'));
 +$result .= str_replace(' ','\\ ',preg_quote(mb_substr($pages[$i],$pos),'/'));
--[[BugTrack/514]]もこれで直りました。 -- [[reimy]] &new{2004-01-31 (土) 21:51:43};
-cvsに投入しました。[[cvs:func.php]](v1.4:r1.58) -- [[ぱんだ]] &new{2004-02-29 (日) 23:11:57};

- BugTrack2/319 ([[下>#jeddb01c]]に移動)

//#comment


----
** [1.4.8] AutoAlias 利用時に、generate_trie_regex 関数が返す正規表現が、うまく動作しない場合がある [#jeddb01c]
AutoAlias 導入前は、ページ名に''#'' が使えないこともあって、generate_trie_regex 関数が''#'' をエスケープしていなくても問題がありませんでした。

しかし、[[#01>test/01]] のように((例なので、短めのルールを書いています)) 別名に''#'' を含むAutoAlias 設定をすると、AutoAlias の正規表現にエスケープされていない''#'' が現れ、&br;InlineConverter クラスで使用する際にパターン修飾子x (PCRE_EXTENDED) によって''#'' 以降がコメント扱いされて正規表現に不整合が発生し、エラーとなります。

generate_trie_regex 関数を
		if ($index < ($i - 1)) {
			// Some more keys found
			// Recurse
			$regex .= str_replace(array(' ','#'), array('\\ ','\\#'), preg_quote($char, '/')) .
				generate_trie_regex($array, $index, $i, $pos + 1);
		} else {
			// Not found
			$regex .= str_replace(array(' ','#'), array('\\ ','\\#'),
				preg_quote(mb_substr($array[$index], $pos), '/'));
		}
として''#'' もエスケープするようにすると、正常に表示されるようになりました。 -- 名無しさん &new{2009-03-20 (金) 00:21:26};

--------
- 把握しました。CVSリポジトリも追いました。こちらは [[BugTrack/502]] の続きのようですので、そこに集約しましょう((いつ誰がやってもいいですが、自分は今日はここまで))。zzz -- [[henoheno]] &new{2009-03-25 (水) 23:57:13};

- BugTrack2/319 よりコピーしました。&br;ところで、[[cvs:lib/func.php]] (1.94) のChangeLog は「generate_trie_regex(): More readable comments」となっていて、実際にコメントの修正以外は入っていないみたいなんですが・・・  -- 名無しさん &new{2009-03-26 (木) 17:35:23};
-- すみません。履歴を追いかけただけで修正はこれから~、な状態みたいですね。 -- 名無しさん &new{2009-03-26 (木) 22:04:27};
- [[cvs:lib/func.php]] (1.95, 1.98, 1.99): preg_quote_extended() を追加。上のメッセージに対比させる形で取り上げるならば、こういう修正になります。
 +// preg_quote(), and also escape PCRE_EXTENDED-related chars
 +// REFERENCE: http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
 +// REFERENCE: http:// www.php.net/manual/en/reference.pcre.pattern.modifiers.php
 +// NOTE: Some special whitespace characters may warned by PCRE_EXTRA
 +//       because of mismatch-possibility between PCRE_EXTENDED and '[:space:]#'.
 +function preg_quote_extended($string, $delimiter = NULL)
 +{
 +	// Escape some more chars
 +	$regex_from = '/([[:space:]#])/';
 +	$regex_to   = '\\\\$1';
 +
 +	if (is_string($delimiter) && preg_match($regex_from, $delimiter)) {
 +		$delimiter = NULL;
 +	}
 +
 +	return preg_replace($regex_from, $regex_to, preg_quote($string, $delimiter));
 +}
 +
  // Generate one compact regex for quick reTRIEval,
  // that just matches with all $array-values.
  //
 @@ -647,13 +663,11 @@
  		if ($index < ($i - 1)) {
  			// Some more keys found
  			// Recurse
 -			$regex .= str_replace(' ', '\\ ', preg_quote($char, '/')) .
 +			$regex .= preg_quote_extended($char, '/') .
  				generate_trie_regex($array, $index, $i, $pos + 1);
  		} else {
  			// Not found
 -			$regex .= str_replace(' ', '\\ ',
 -				preg_quote(mb_substr($array[$index], $_pos), '/'));
 +			$regex .= preg_quote_extended(mb_substr($array[$index], $_pos), '/');
  		}
  		$index = $i;
  	}
-- 今までの経緯からすると、PCRE_EXTENDED の仕様を認識していたにもかかわらず、関連する対象文字を全てカバーしていなかったというのが問題のように見えます。足りないケアは # についてだけではないので、#を足すだけでは解決にはなりません。そこで、最終的に[:space:]と#についても追加でエスケープする関数 preg_quote_extended() を用意しました。これで、generate_trie_regex() がもう少し汎用化された関数になったはずです。 ((とっくに汎用化したと思っていたのに・・・。 http://www.pcre.org/pcre.txt によると、 \s は Perlとの互換性を維持するため VT <vertical tab> 文字を含んでいません。[:space:] は含んでいます。)) -- [[henoheno]] &new{2009-03-29 (日) 11:46:53};
-- 今までの経緯からすると、PCRE_EXTENDED の仕様を認識していたにもかかわらず、関連する対象文字を全てカバーしていなかったというのが問題のように見えます。足りないケアは # についてだけではないので、#を足すだけでは解決にはなりません。そこで、最終的に[:space:]と#についても追加でエスケープする関数 preg_quote_extended() を用意しました。これで、generate_trie_regex() がもう少し汎用化された関数になったはずです。 ((とっくに汎用化したと思っていたのに・・・。 http:// www.pcre.org/pcre.txt によると、 \s は Perlとの互換性を維持するため VT <vertical tab> 文字を含んでいません。[:space:] は含んでいます。)) -- [[henoheno]] &new{2009-03-29 (日) 11:46:53};
-- 補足: PCRE_EXTENDED が無視する whitespace と、 [:space:] に属するwhitespaceにはひょっとしたら多少のずれがあるかもしれません。そしてそのずれが、PCRE_EXTRA によりエラーとして報告される事があるかもしれません。現状は無害((こうした正規表現から「文字列の配列」を取り戻そうとした場合には、余計なバックスラッシュが邪魔になる))であろうため、今回そこまでは追っていません。 -- [[henoheno]] &new{2009-03-29 (日) 11:55:17};
- lib/func.php (1.100) で、特に問題はないことを確認しました。 -- 名無しさん &new{2009-03-30 (月) 22:24:34};
- CzMaPgfOzhNLKbrVvR -- [[qwqjrmr]] &new{2014-09-05 (金) 00:46:07};

#comment
//#comment

*** その他: [#tb4ec63c]
- 本件に付随し、generate_trie_regex() について若干の整理を行いました。他の修正とはdiffが別になるようにcommitしてあります。詳細はdiffを見て下さい -- [[henoheno]] &new{2009-03-29 (日) 11:57:34};
-- [[cvs:lib/func.php]] (1.94) 関数ヘッダの整理
-- [[cvs:lib/func.php]] (1.96) 文字列の連結方法を修正 (ページが大量にある場合、若干処理が早くなる) ((preg_quote_extended() を外出しにしたため、トータルでは遅いはず))
-- [[cvs:lib/func.php]] (1.97) 内部変数の名前をそれらしく修正
-- [[cvs:lib/func.php]] (1.100) "if (mb_substr($array[$i], $_pos, 1) != $char)" を関数呼び出しの度に一回以上余計に実行していた
- 本件に付随し、generate_trie_regex() をもう少し観察し直しましたが、正規表現が無駄に長くなる場面があります。以下のような処理をさせるためには、作り直さないと実現できないでしょう -- [[henoheno]] &new{2009-03-29 (日) 12:10:39};
 こうなる部分は (?:1(?:0|1|2|3|4|5|6|7|8|9)|2(?:0|1|2|3|4|5|6|7|8|9))
 本来こうできる [12][0-9]
-- そもそもこうした(木構造を正規表現に落とし込むような)機構は誰かがライブラリ化しているものではないのかな・・・ -- [[henoheno]] &new{2009-03-29 (日) 12:18:10};

#comment
//#comment

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Site admin: PukiWiki Development Team

PukiWiki 1.5.4+ © 2001-2022 PukiWiki Development Team. Powered by PHP 8.2.12. HTML convert time: 0.120 sec.

SourceForge