PHP-带有特殊字符的X字符后的子字符串

PHP-带有特殊字符的X字符后的子字符串,php,special-characters,Php,Special Characters,对不起,这个标题,我真的不知道该怎么说 我经常有一个字符串需要在X个字符后剪切,我的问题是这个字符串通常包含特殊字符,如:è 所以,我想知道,他们是在PHP中知道的方式,而不改变我的字符串,如果我在剪断我的字符串,我就在一个特殊的字符的中间。< /P> 示例 This is my string with a special char : &egrave; - and I want it to cut in the middle of the "&egrave;" bu

对不起,这个标题,我真的不知道该怎么说

我经常有一个字符串需要在X个字符后剪切,我的问题是这个字符串通常包含特殊字符,如:è

所以,我想知道,他们是在PHP中知道的方式,而不改变我的字符串,如果我在剪断我的字符串,我就在一个特殊的字符的中间。< /P> 示例

This is my string with a special char : &egrave; - and I want it to cut in the middle of the "&egrave;" but still keeping the string intact
所以现在我的子字符串结果是:

This is my string with a special char : &egra
但我想要这样的东西:

This is my string with a special char : &egrave;

我认为您必须使用strpos和strrpos的组合来查找下一个和上一个空格,解析空格之间的文本,对照已知的特殊字符列表检查是否匹配,如果匹配,则将“剪切”扩展到下一个空格的位置。如果您有一个您现在拥有的代码示例,我们可以给您一个更好的答案。

您可以首先使用html_entity_decode()对所有html实体进行解码。然后分开你的绳子。然后使用htmlentities()对实体进行重新编码

$decoded_string = html_entity_decode($original_string);
// implement logic to split string here

// then for each string part do the following:
$encoded_string_part = htmlentities($split_string_part);

最长的HTML实体长度为10个字符,包括符号和分号。如果要在
X
字节处剪切字符串,请检查字节
X-9
X-1
中是否有与符。如果相应的分号出现在byte
X
或更高版本,请在分号之后而不是byte
X
之后剪切字符串

但是,如果您愿意预处理字符串,Mike的解决方案将更加准确,因为他将字符串切割为
X
个字符,而不是字节。

最好的解决方案是将文本存储为UTF-8,而不是将其存储为HTML实体。除此之外,如果您不介意计数被关闭(
&grave;
等于一个字符,而不是7),那么下面的代码段应该可以工作:

<?php
$string = 'This is my string with a special char : &egrave; - and I want it to cut in the middle of the "&egrave;" but still keeping the string intact';
$cut_string = htmlentities(mb_substr(html_entity_decode($string, NULL, 'UTF-8'), 0, 45), NULL, 'UTF-8')."<br><br>";

这里最好的做法是将字符串存储为UTF-8,不带任何html实体,并使用
mb.*
函数族和
utf8
作为编码

但是,如果您的字符串是ASCII或iso-8859-1/win1252,则可以使用mb_字符串库的特殊
HTML-ENTITIES
编码:

$s = 'This is my string with a special char : &egrave; - and I want it to cut in the middle of the "&egrave;" but still keeping the string intact';
echo mb_substr($s, 0, 40, 'HTML-ENTITIES');
echo mb_substr($s, 0, 41, 'HTML-ENTITIES');
但是,如果您的基础字符串是UTF-8或其他一些多字节编码,则使用
HTML-ENTITIES
不安全的!这是因为
HTML-ENTITIES
真正的意思是“以高位字符作为HTML实体的win1252”。这是一个可能出错的示例:

// Assuming that é is in utf8:
mb_substr('é ', 0, 2, 'HTML-ENTITIES') === '&Atilde;&copy;'
// should be '&eacute; '
当字符串采用多字节编码时,必须在拆分之前将所有html实体转换为通用编码。例如:

$strings_actual_encoding = 'utf8';
$s_noentities = html_entity_decode($s, ENT_QUOTES, $strings_actual_encoding); 
$s_trunc_noentities =  mb_substr($s_noentities, 0, 41, $strings_actual_encoding);

一个我不太喜欢的小bruteforce解决方案是一个
PCRE
表达式,假设您希望传递80个字符,而最长的HTML表达式可能是7个字符长:

$regex = '~^(.{73}([^&]{7}|.{0,7}$|[^&]{0,6}&[^;]+;))(.*)~mx'
// Note, this could return a bit of shorter text
return preg_replace( $regexp, '$1', $text);
让你知道:

  • {73}
    -73个字符
  • [^&]{7}
    -好的,我们可以用任何不包含&
  • {0,7}$
    -记住可能的结尾(这不必要,因为较短的文本根本不匹配)
  • [^&]{0,6}&[^;]+-最多6个字符(您将在第79位),然后
    &
    完成
看起来好得多但需要一点数字游戏的东西是:

// check whether $text is at least $N chars long :)
if( strlen( $text) < $N){
    return;
}

// Get last &
$pos = strrpos( $text, '&', $N);

// We're not young anymore, we have to check this too (not entries at all) :)
if( $pos === false){
    return substr( $text, 0, $N);
}

// Get Last
$end = strpos( $text, ';', $N);

// false wouldn't be smaller then 0 (entry open at the beginning
if( $end === false){
    $end = -1;
}

// Okay, entry closed (; is after &)(
if( $end > $pos){
   return substr($text, 0, $N);
}

// Now we need to find first ;
$end = strpos( $text, ';', $N)
if( $end === false){
    // Not valid HTML, not closed entry, do whatever you want
}

return substr($text, 0, $end);
//检查$text是否至少有$N个字符长:)
如果(strlen($text)<$N){
返回;
}
//排在最后&
$pos=strrpos($text,&',$N);
//我们不再年轻了,我们也必须检查这一点(根本不是条目):)
如果($pos==false){
返回substr($text,0,$N);
}
//排在最后
$end=strpos($text,“;”,$N);
//false不会小于0(条目在开始时打开
如果($end==false){
$end=-1;
}
//好的,入口关闭(;在&)之后(
如果($end>$pos){
返回substr($text,0,$N);
}
//现在我们需要先找到;
$end=strpos($text,“;”,$N)
如果($end==false){
//无效的HTML,未关闭的条目,请执行任意操作
}
返回substr($text,0,$end);

检查数,索引中可能有+/- 1的地方……/P>什么应该发生?你的计数是否在一个正常单词的中间?@ cFRAK我们删掉这个词……(我们想删减)问题是,在像这样的普通字符串中,
è;
与任何其他单词都是一样的。它没有什么特别之处。你可以解析它或使用正则表达式。+1-我只是想发布这个(尽管有一个例子).你会添加和举例吗?答案很好,但如果我们使用10000000字的字符串,可能会比其他解决方案慢。但如果他在说出原始字符串的前100个字符后,在解码实体后,他会包含更多可能不需要的原始字符串文本。对于每10个字符的“特殊字符”解码完成后,原始字符串中又添加了9个字符。即“&;”是4个字符,“&”是1。当您可以指望不将
“某物”之类的内容混合在一起时,这非常好
由于……但是,如果我给你类似于
ná;ná;ná;ná;蝙蝠侠的字符串,
…结果会比期望的长得多。这是目前最好的解决方案;)我会等待10-15分钟,如果他们的解决方案不是更好的,我会将你标记为已接受;)此解决方案没有考虑在多字节编码中拆分字符串所涉及的危险。从末尾循环10个字符可能比我的解决方案更有效;)+1,但能否请您提供最长HTML实体的源代码是10个字符长?@Vyktor,中定义的最长符号是
&thetasym
@FrancisAvila,这是正确的,但我假设在这种情况下,任何多字节字符都会转换为HTML实体。我希望知道原因:,如果您的基础字符串是UTF-8或其他多字节编码,使用HTML实体是不安全的@Hipny,它本身不是