PHP mb_split(),捕获定界符

标签 php delimiter capture preg-split multibyte

preg_split 有一个可选的 PREG_SPLIT_DELIM_CAPTURE 标志,它还会返回返回数组中的所有分隔符。 mb_split 没有。

有什么方法可以拆分多字节字符串(不仅是 UTF-8,还有所有类型)并捕获分隔符?

我正在尝试制作一个多字节安全的换行符拆分器,保留换行符,但更喜欢更通用的解决方案。

解决方案 感谢用户 Casimir et Hippolyte,我构建了一个解决方案并将其发布在 github 上 ( https://github.com/vanderlee/PHP-multibyte-functions/blob/master/functions/mb_explode.php ),它允许所有 preg_split 标志:

/**
 * A cross between mb_split and preg_split, adding the preg_split flags
 * to mb_split.
 * @param string $pattern
 * @param string $string
 * @param int $limit
 * @param int $flags
 * @return array
 */
function mb_explode($pattern, $string, $limit = -1, $flags = 0) {       
    $strlen = strlen($string);      // bytes!   
    mb_ereg_search_init($string);

    $lengths = array();
    $position = 0;
    while (($array = mb_ereg_search_pos($pattern)) !== false) {
        // capture split
        $lengths[] = array($array[0] - $position, false, null);

        // move position
        $position = $array[0] + $array[1];

        // capture delimiter
        $regs = mb_ereg_search_getregs();           
        $lengths[] = array($array[1], true, isset($regs[1]) && $regs[1]);

        // Continue on?
        if ($position >= $strlen) {
            break;
        }           
    }

    // Add last bit, if not ending with split
    $lengths[] = array($strlen - $position, false, null);

    // Substrings
    $parts = array();
    $position = 0;      
    $count = 1;
    foreach ($lengths as $length) {
        $is_delimiter   = $length[1];
        $is_captured    = $length[2];

        if ($limit > 0 && !$is_delimiter && ($length[0] || ~$flags & PREG_SPLIT_NO_EMPTY) && ++$count > $limit) {
            if ($length[0] > 0 || ~$flags & PREG_SPLIT_NO_EMPTY) {          
                $parts[]    = $flags & PREG_SPLIT_OFFSET_CAPTURE
                            ? array(mb_strcut($string, $position), $position)
                            : mb_strcut($string, $position);                
            }
            break;
        } elseif ((!$is_delimiter || ($flags & PREG_SPLIT_DELIM_CAPTURE && $is_captured))
               && ($length[0] || ~$flags & PREG_SPLIT_NO_EMPTY)) {
            $parts[]    = $flags & PREG_SPLIT_OFFSET_CAPTURE
                        ? array(mb_strcut($string, $position, $length[0]), $position)
                        : mb_strcut($string, $position, $length[0]);
        }

        $position += $length[0];
    }

    return $parts;
}

最佳答案

只能使用 preg_split 捕获分隔符并且在其他函数中不可用。

所以三种可能:

1) 将您的字符串转换为 UTF8,使用 preg_splitPREG_SPLIT_DELIM_CAPTURE ,并使用 array_map将每个项目转换为原始编码。

这种方式比较简单。第二种方式并非如此。 (请注意,一般来说,始终使用 UTF8 比处理奇异编码更简单)

2) 代替您需要使用的 split-like 函数,例如 mb_ereg_search_regs 获取匹配的部分并像这样构建模式:

delimiter|all_that_is_not_the_delimiter

(请注意,交替的两个分支必须互斥,并注意以在结果之间产生不可能的间隙的方式编写它们。第一部分必须在字符串的开头,最后一部分必须在末尾。每个部分都必须与前面的部分连续,依此类推。)

3) 使用 mb_splitlookarounds .根据定义,lookarounds 是零宽度断言,不匹配任何字符,只匹配字符串中的位置。所以你可以使用这种匹配定界符之前或之前位置的模式:

(?=delimiter)|(<=delimiter)

(这种方式的局限性是lookbehind中的subpattern不能变长(也就是说里面不能使用量词),但是可以是定长交替子模式:(?<=subpat1|subpat2|subpat3) )

关于PHP mb_split(),捕获定界符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30605173/

相关文章:

java - 如何使用 CAPTURE 绑定(bind)创建 AST?

使用智能手机相机拍摄 html5 照片,图像顺时针旋转

java - 捕获 DOS(命令提示符)的输出并显示在 JAVA Frame 中

javascript - strip 化 IBAN 元素错误 'The type ` sepa_debit` 不是有效的源类型。

php - 使用动态创建的表单创建 MySQL 表

awk - 使用 awk 在每 n 列的空格分隔文件中插入分隔符(逗号)

parsing - D3 删除千位逗号分隔符

java - 从 Objective-C 发送到 Java 再到 SQL 的条形码的良好分隔符

php - 当进程意外死亡时,flock'ed 文件会被解锁吗?

php - 在 PHP 中有没有办法确定 while 循环中第一次使用值?