【问题标题】:Regular expression for utf-8 string sliceing at linebreaks or after a number of charactersutf-8 字符串在换行符处或多个字符后切片的正则表达式
【发布时间】:2013-09-23 21:31:40
【问题描述】:

我在网上找到了一个函数,它使用正则表达式来迭代字符串并在指定数量的字符后插入换行符,因此它将适合具有固定宽度的窄表格单元格。 这是函数:

/**
     * wordwrap for utf8 encoded strings
     *
     * @param string $str
     * @param integer $len
     * @param string $what
     * @return string
     * @author Milian Wolff <mail@milianw.de>
     */

    function utf8_wordwrap($str, $width, $break, $cut = false) {

    if (!$cut || $_SESSION['wordwrap']) {
        $regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.'}#';
    } else {
            return $str; //if no wordwrap turned on, returns the original string
    }
    if (function_exists('mb_strlen')) {
        $str_len = mb_strlen($str,'UTF-8');
    } else {
        $str_len = preg_match_all('/[\x00-\x7F\xC0-\xFD]/', $str, $var_empty);
    }
    $while_what = ceil($str_len / $width);
    $i = 1;
    $return = '';
    while ($i < $while_what) {
        preg_match($regexp, $str,$matches);
        $string = $matches[0];
        $return .= $string.$break;
        $str = substr($str, strlen($string));
        $i++;
    }
    return $return.$str;
    }

这里是正则表达式:

#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){20}#

如果它与 while 循环结合使用,直到字符串中出现换行符,它就可以很好地完成工作。

示例字符串:

1. first
2. second
3. third

prag_match 的输出:

array (
  0 => '1. first
2. second
3',
)

所以它只计算第 20 个字符,并返回它。

我需要的是: 要使其返回所有内容,直到新行字符 (\n) 或如果没有,则返回前 20 个字符。 所以这种情况下的输出会是这样的:

array (
      0 => '1. first',
      1 => '2. second',
      2 => '3. third'
    )

更新: 我尝试了史蒂夫罗宾斯的答案,它运行良好,直到字符串中有一些规范的 UTF-8 字符。这是我的错,我一开始没有提供一个像样的例子。 它的作用如下:

<?php

header('Content-type: text/html; charset=UTF-8');
$input = '1. first
2. second
3. third
ez eg nyoulőűúúú3456789öüö987654323456789öü
pam
param';

$output = array();

foreach (explode("\n", $input) as $value) {
    foreach (str_split($value, 20) as $v) {
        $trimmed = trim($v);
        if (!empty($trimmed))
            $output[] = $trimmed;
    }
}

var_dump($output);

输出是:

array(8) {
  [0]=>
  string(8) "1. first"
  [1]=>
  string(9) "2. second"
  [2]=>
  string(8) "3. third"
  [3]=>
  string(20) "ez eg nyoulőűúú�"
  [4]=>
  string(20) "�3456789öüö987654"
  [5]=>
  string(13) "323456789öü"
  [6]=>
  string(3) "pam"
  [7]=>
  string(5) "papam"
}

http://codepad.org/Gt4CshXt

【问题讨论】:

  • “所以它会适合一个固定宽度的窄表格单元格”——而不是撕裂你的内容(这也会影响搜索引擎如何看待它),为什么不只使用CSS?毕竟,您要解决的只是显示问题……developer.mozilla.org/en-US/docs/Web/CSS/word-wrap

标签: php regex string utf-8 word-wrap


【解决方案1】:

为什么要使用正则表达式?

<?php

$input = '1. first
2. second
3. third';

$output = array();

foreach (explode("\n", $input) as $value) {
    foreach (str_split($value, 20) as $v) {
        $trimmed = trim($v);
        if (!empty($trimmed))
            $output[] = $trimmed;
    }
}

var_dump($output);

给予

array(3) {
  [0]=>
  string(8) "1. first"
  [1]=>
  string(9) "2. second"
  [2]=>
  string(8) "3. third"
}

示例:http://codepad.org/OoillEUu

【讨论】:

    【解决方案2】:

    感谢大家的努力! 我找到了解决方案here

    <?php
    header('Content-Type: text/html; charset=utf-8');
    $input = '1. first
    2. second
    3. third
    ez eg nyoulőűúúú3456789öüö987654323456789öü
    pam
    papam';
    
    var_dump(utf8_wordwrap($input,20,"<br>",true));
    function utf8_wordwrap($string, $width=20, $break="\n", $cut=false)
    {
      if($cut) {
        // Match anything 1 to $width chars long followed by whitespace or EOS,
        // otherwise match anything $width chars long
        $search = '/(.{1,'.$width.'})(?:\s|$)|(.{'.$width.'})/uS';
        $replace = '$1$2'.$break;
      } else {
        // Anchor the beginning of the pattern with a lookahead
        // to avoid crazy backtracking when words are longer than $width
        $pattern = '/(?=\s)(.{1,'.$width.'})(?:\s|$)/uS';
        $replace = '$1'.$break;
      }
      return preg_replace($search, $replace, $string);
    }
    ?>
    string '1. first
    <br>2. second
    <br>3. third
    <br>ez eg<br>nyoulőűúúú3456789öüö<br>987654323456789öü
    <br>pam
    <br>papam<br>' (length=122)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 1970-01-01
      • 2012-07-27
      • 2019-11-09
      相关资源
      最近更新 更多