10

私は持っているpreg_match_all('/[aäeëioöuáéíóú]/u', $in, $out, PREG_OFFSET_CAPTURE);

場合$in = 'hëllo' $out:

array(1) {
[0]=>
  array(2) {
  [0]=>
    array(2) {
      [0]=>
      string(2) "ë"
  [1]=>
  int(1)
}
[1]=>
array(2) {
  [0]=>
  string(1) "o"
  [1]=>
  int(5)
  }
}
}

の位置はo4 である必要があります。この問題についてオンラインで読みました (ë取得は 2 としてカウントされます)。これに対する解決策はありますか?と似たようなのを見mb_substrたことがありますが、こんなものはありpreg_match_allますか?

preg_match_all一種の関連: それらは Pythonと同等ですか? (文字列内の位置と一致する配列を返す)

4

4 に答える 4

7

これはバグではなく、PREG_OFFSET_CAPTURE文字列内の文字のバイト オフセットを指します。

mb_ereg_search_pos同じように動作します。可能性の 1 つは、エンコードを UTF-32 に変更してから、位置を 4 で割ることです (すべての Unicode コード単位は UTF-32 では 4 バイトのシーケンスとして表されるため)。

mb_regex_encoding("UTF-32");
$string = mb_convert_encoding('hëllo', "UTF-32", "UTF-8");
$regex =  mb_convert_encoding('[aäeëioöuáéíóú]', "UTF-32", "UTF-8");
mb_ereg_search_init ($string, $regex);
$positions = array();
while ($r = mb_ereg_search_pos()) {
    $positions[] = reset($r)/4;
}
print_r($positions);

与えます:

配列
(
    [0] => 1
    [1] => 4
)

バイナリ位置をコード単位位置に変換することもできます。UTF-8 の場合、次善の実装は次のとおりです。

function utf8_byte_offset_to_unit($string, $boff) {
    $result = 0;
    for ($i = 0; $i < $boff; ) {
        $result++;
        $byte = $string[$i];
        $base2 = str_pad(
            base_convert((string) ord($byte), 10, 2), 8, "0", STR_PAD_LEFT);
        $p = strpos($base2, "0");
        if ($p == 0) { $i++; }
        elseif ($p <= 4) { $i += $p; }
        else  { return FALSE; }
    }
    return $result;
}
于 2010-08-08T00:23:51.463 に答える
5

preg_match() の結果が一致した後に使用する簡単な回避策があります。次のように、すべての一致結果を繰り返し、位置の値を再割り当てする必要があります。

$utfPosition = mb_strlen(substr($wholeSubjectString, 0, $capturedEntryPosition), 'utf-8');

Windows の php 5.4 でテスト済み。マルチバイト PHP 拡張機能のみに依存します。

于 2014-02-27T09:39:19.707 に答える
0

PHP は Unicode をあまりサポートしていないため、preg_* を含む多くの文字列関数は、依然として文字ではなくバイトをカウントします。

文字列のエンコードとデコードで解決策を見つけようとしましたが、最終的にはすべて preg_match_all 関数に行き着きました。

Python について: Python 正規表現の matchobject には、デフォルトで mo.start() と mo.end() の一致位置が含まれています。参照: http://docs.python.org/library/re.html#finding-all-adverbs-and-their-positions

于 2010-02-02T21:14:19.733 に答える
0

$stringUTF-8を正規表現で分割する別の方法は、 function を使用することpreg_split()です。これが私の実用的なソリューションです:

    $result = preg_split('~\[img/\d{1,}/img\]\s?~', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

PHP 5.3.17

于 2014-11-19T00:06:56.777 に答える