PHP、PREGおよびUTF-8

この投稿では、preg _ *()関数を使用してマルチバイト文字列を操作するPHP5について説明します。



一般に、インターネット上で説明されていましたが、今日に関係のある一般的に興味深い状況に気付きました(trim()についての最近の投稿に関連して問題が浮上しました)。



たとえば、小さなスクリプトを示します。



<?<br> <br> print ": " . setLocale ( LC_ALL , 0 ) . "\n" ;<br> <br> /**<br> * preg_match_all<br> * @param string $comment <br> * @param string $pattern preg_match_all<br> * @param bool $usePatch <br> * @return void<br> */<br> <br> function preg_test ( $comment , $pattern , $usePatch = false ) {<br> <br> $test = "one three" ;<br> <br> print "\n<strong>{$comment}:</strong> <u>{$pattern}</u>\n" ;<br> <br> if ( $usePatch ) mb_preg_match_all ( $pattern , $test , $matches , PREG_OFFSET_CAPTURE );<br> else preg_match_all ( $pattern , $test , $matches , PREG_OFFSET_CAPTURE );<br> <br> foreach ( $matches [ 0 ] as $v ) print " : «{$v[0]}», : {$v[1]}\n" ;<br> <br> }<br> <br> /**<br> * , <br> */<br> <br> function mb_preg_match_all (<br> $ps_pattern ,<br> $ps_subject ,<br> & $pa_matches ,<br> $pn_flags = PREG_PATTERN_ORDER ,<br> $pn_offset = 0 ,<br> $ps_encoding = NULL<br> ) {<br> <br> // WARNING! - All this function does is to correct offsets, nothing else:<br> //(code is independent of PREG_PATTER_ORDER / PREG_SET_ORDER)<br> <br> if ( is_null ( $ps_encoding )) $ps_encoding = mb_internal_encoding ();<br> <br> $pn_offset = strlen ( mb_substr ( $ps_subject , 0 , $pn_offset , $ps_encoding ));<br> $ret = preg_match_all ( $ps_pattern , $ps_subject , $pa_matches , $pn_flags , $pn_offset );<br> <br> if ( $ret && ( $pn_flags & PREG_OFFSET_CAPTURE ))<br> foreach( $pa_matches as & $ha_match )<br> foreach( $ha_match as & $ha_match )<br> $ha_match [ 1 ] = mb_strlen ( substr ( $ps_subject , 0 , $ha_match [ 1 ]), $ps_encoding );<br> <br> return $ret ;<br> <br> }<br> <br> preg_test ( "« »" , "/[\w]+/i" );<br> preg_test ( "Character range" , "/[-a-z]+/i" );<br> preg_test ( "« » «/u»" , "/[\w]+/ui" );<br> preg_test ( "Character range «/u»" , "/[-a-z]+/ui" );<br> preg_test ( " «\pL», «/u»" , "/[\pL]+/i" );<br> preg_test ( " «\p{Cyrillic}», «/u»" , "/[\p{Cyrillic}]+/i" );<br> preg_test ( "(!) «\pL» " , "/[\pL]+/i" , true );<br> <br> $source = highlight_file ( __FILE__ , true );<br> <br> ?>







作業例はhttp://test.dis.dj/utf/にあります。



彼が見たものからどのような結論を引き出すべきか:

  1. 行の先頭からのオフセットは、常にバイト単位で考慮されます。

    「1」の3バイト+

    1バイトのスペース+

    3×2バイト「2」+

    1バイトのスペース+

    3×2バイト「2」+

    1バイトスペース=

    18バイト

    しかし、する必要があります

    3 + 1 + 3 + 1 + 3 + 1 = 12文字
  2. 「/ u」キーと「ユニコード文字」を意味する「\ pL」修飾子を持つ「文字範囲」のみがキリル文字を正しく認識します
  3. キリルアルファベットの修飾子「\ w」はまったく機能せず、キー「/ u」でも役に立たない
  4. Windows Server 2008を実行しているサーバーでは、何らかの理由で、最初の設計は機能しましたが、「/ u」スイッチは使用できなくなりました。


便利なリンク:



それでは、ヘッダー()の前に3バイトを出力してスクリプトをあふれさせるBOMを含むUTF6の文字列の通常のサポートが約束されているPHP6を待っています。 実際、PHP6では一般に多くのボーナスがあります...



PS断食は決して「アメリカの発見」であると主張しません-私はちょうど私が知っている情報を集めました。



UPD。 議論の中で、次の置換\ wに行きました:推奨されるコングロマリット "(?:\ P {L} | \ p {M} | \ p {D} | \ p {Pc})"、または "[\ p {L} \ p {Nd}]」(短いものが必要な場合)。 どうもありがとう。



All Articles