マルチバイトでも安全でwordwrap()機能ではUTF-8
質問
PHPの wordwrap()
機能が正しく働いていなかったマルチバイト文字列のようにUTF-8です。
あのいくつかの例mb安全機能は、クラウドコンピューティングとは一部異なる試験データなな課題となりました。
この機能は同じパラメータとして wordwrap()
.
具体的には必ずです:
- カット中の単語の場合
$cut = true
, なカット中の単語その他 - いても、このような余分なスペースの言葉の場合
$break = ' '
- もの作業
$break = "\n"
- 仕事のためのASCII、有効なすべてUTF-8
解決 8
この1はうまく動作しているようです...
function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false, $charset = null) {
if ($charset === null) $charset = mb_internal_encoding();
$pieces = explode($break, $str);
$result = array();
foreach ($pieces as $piece) {
$current = $piece;
while ($cut && mb_strlen($current) > $width) {
$result[] = mb_substr($current, 0, $width, $charset);
$current = mb_substr($current, $width, 2048, $charset);
}
$result[] = $current;
}
return implode($break, $result);
}
他のヒント
私は私のために任意の作業コードを発見していません。ここで私が書いたものです。私にとってはそれが働いている、それはおそらく最速ではないと思っています。
function mb_wordwrap($str, $width = 75, $break = "\n", $cut = false) {
$lines = explode($break, $str);
foreach ($lines as &$line) {
$line = rtrim($line);
if (mb_strlen($line) <= $width)
continue;
$words = explode(' ', $line);
$line = '';
$actual = '';
foreach ($words as $word) {
if (mb_strlen($actual.$word) <= $width)
$actual .= $word.' ';
else {
if ($actual != '')
$line .= rtrim($actual).$break;
$actual = $word;
if ($cut) {
while (mb_strlen($actual) > $width) {
$line .= mb_substr($actual, 0, $width).$break;
$actual = mb_substr($actual, $width);
}
}
$actual .= ' ';
}
}
$line .= trim($actual);
}
return implode($break, $lines);
}
/**
* 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) {
$regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.',}\b#U';
} else {
$regexp = '#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){'.$width.'}#';
}
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;
}
合計時間:0.0020880699は良い時間です:)
がえのない扱いでしたが毎利用の場合は、あります。このコードに基づく Drupalの AbstractStringWrapper::wordWrap
.
<?php
/**
* Wraps any string to a given number of characters.
*
* This implementation is multi-byte aware and relies on {@link
* http://www.php.net/manual/en/book.mbstring.php PHP's multibyte
* string extension}.
*
* @see wordwrap()
* @link https://api.drupal.org/api/drupal/core%21vendor%21zendframework%21zend-stdlib%21Zend%21Stdlib%21StringWrapper%21AbstractStringWrapper.php/function/AbstractStringWrapper%3A%3AwordWrap/8
* @param string $string
* The input string.
* @param int $width [optional]
* The number of characters at which <var>$string</var> will be
* wrapped. Defaults to <code>75</code>.
* @param string $break [optional]
* The line is broken using the optional break parameter. Defaults
* to <code>"\n"</code>.
* @param boolean $cut [optional]
* If the <var>$cut</var> is set to <code>TRUE</code>, the string is
* always wrapped at or before the specified <var>$width</var>. So if
* you have a word that is larger than the given <var>$width</var>, it
* is broken apart. Defaults to <code>FALSE</code>.
* @return string
* Returns the given <var>$string</var> wrapped at the specified
* <var>$width</var>.
*/
function mb_wordwrap($string, $width = 75, $break = "\n", $cut = false) {
$string = (string) $string;
if ($string === '') {
return '';
}
$break = (string) $break;
if ($break === '') {
trigger_error('Break string cannot be empty', E_USER_ERROR);
}
$width = (int) $width;
if ($width === 0 && $cut) {
trigger_error('Cannot force cut when width is zero', E_USER_ERROR);
}
if (strlen($string) === mb_strlen($string)) {
return wordwrap($string, $width, $break, $cut);
}
$stringWidth = mb_strlen($string);
$breakWidth = mb_strlen($break);
$result = '';
$lastStart = $lastSpace = 0;
for ($current = 0; $current < $stringWidth; $current++) {
$char = mb_substr($string, $current, 1);
$possibleBreak = $char;
if ($breakWidth !== 1) {
$possibleBreak = mb_substr($string, $current, $breakWidth);
}
if ($possibleBreak === $break) {
$result .= mb_substr($string, $lastStart, $current - $lastStart + $breakWidth);
$current += $breakWidth - 1;
$lastStart = $lastSpace = $current + 1;
continue;
}
if ($char === ' ') {
if ($current - $lastStart >= $width) {
$result .= mb_substr($string, $lastStart, $current - $lastStart) . $break;
$lastStart = $current + 1;
}
$lastSpace = $current;
continue;
}
if ($current - $lastStart >= $width && $cut && $lastStart >= $lastSpace) {
$result .= mb_substr($string, $lastStart, $current - $lastStart) . $break;
$lastStart = $lastSpace = $current;
continue;
}
if ($current - $lastStart >= $width && $lastStart < $lastSpace) {
$result .= mb_substr($string, $lastStart, $lastSpace - $lastStart) . $break;
$lastStart = $lastSpace = $lastSpace + 1;
continue;
}
}
if ($lastStart !== $current) {
$result .= mb_substr($string, $lastStart, $current - $lastStart);
}
return $result;
}
?>
function mb_wordwrap($str, $width = 74, $break = "\r\n", $cut = false)
{
return preg_replace(
'~(?P<str>.{' . $width . ',}?' . ($cut ? '(?(?!.+\s+)\s*|\s+)' : '\s+') . ')(?=\S+)~mus',
'$1' . $break,
$str
);
}
ここで私は他人のからインスピレーションを取ってコード化されているマルチバイト折り返す機能は、インターネット上で見つかっている。
function mb_wordwrap($long_str, $width = 75, $break = "\n", $cut = false) {
$long_str = html_entity_decode($long_str, ENT_COMPAT, 'UTF-8');
$width -= mb_strlen($break);
if ($cut) {
$short_str = mb_substr($long_str, 0, $width);
$short_str = trim($short_str);
}
else {
$short_str = preg_replace('/^(.{1,'.$width.'})(?:\s.*|$)/', '$1', $long_str);
if (mb_strlen($short_str) > $width) {
$short_str = mb_substr($short_str, 0, $width);
}
}
if (mb_strlen($long_str) != mb_strlen($short_str)) {
$short_str .= $break;
}
return $short_str;
}
いけない」でUTF-8を使用するためのconfigure PHPに忘れます:
ini_set('default_charset', 'UTF-8');
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
私はこれが役立つことを願っています。 ギヨーム
ただ、私がネットにあるいくつかの選択肢を共有したいと思います。
<?php
if ( !function_exists('mb_str_split') ) {
function mb_str_split($string, $split_length = 1)
{
mb_internal_encoding('UTF-8');
mb_regex_encoding('UTF-8');
$split_length = ($split_length <= 0) ? 1 : $split_length;
$mb_strlen = mb_strlen($string, 'utf-8');
$array = array();
for($i = 0; $i < $mb_strlen; $i += $split_length) {
$array[] = mb_substr($string, $i, $split_length);
}
return $array;
}
}
mb_str_split
を使用して、あなたはjoin
と言葉を組み合わせること<br>
を使用することができます。
<?php
$text = '<utf-8 content>';
echo join('<br>', mb_str_split($text, 20));
そして最後に、独自のヘルパーを作成し、おそらくmb_textwrap
<?php
if( !function_exists('mb_textwrap') ) {
function mb_textwrap($text, $length = 20, $concat = '<br>')
{
return join($concat, mb_str_split($text, $length));
}
}
$text = '<utf-8 content>';
// so simply call
echo mb_textwrap($text);
ここで私はそれが100%完璧の約束なので、あなたが問題を見れば、より良いものを投稿してくださいすることはできませんが、私自身のテストの数を渡された関数で、私自身の試みだ。
/**
* Multi-byte safe version of wordwrap()
* Seems to me like wordwrap() is only broken on UTF-8 strings when $cut = true
* @return string
*/
function wrap($str, $len = 75, $break = " ", $cut = true) {
$len = (int) $len;
if (empty($str))
return "";
$pattern = "";
if ($cut)
$pattern = '/([^'.preg_quote($break).']{'.$len.'})/u';
else
return wordwrap($str, $len, $break);
return preg_replace($pattern, "\${1}".$break, $str);
}
所属していません StackOverflow