PHP-带有特殊字符的X字符后的子字符串
对不起,这个标题,我真的不知道该怎么说 我经常有一个字符串需要在X个字符后剪切,我的问题是这个字符串通常包含特殊字符,如:è 所以,我想知道,他们是在PHP中知道的方式,而不改变我的字符串,如果我在剪断我的字符串,我就在一个特殊的字符的中间。< /P> 示例PHP-带有特殊字符的X字符后的子字符串,php,special-characters,Php,Special Characters,对不起,这个标题,我真的不知道该怎么说 我经常有一个字符串需要在X个字符后剪切,我的问题是这个字符串通常包含特殊字符,如:è 所以,我想知道,他们是在PHP中知道的方式,而不改变我的字符串,如果我在剪断我的字符串,我就在一个特殊的字符的中间。< /P> 示例 This is my string with a special char : è - and I want it to cut in the middle of the "è" bu
This is my string with a special char : è - and I want it to cut in the middle of the "è" but still keeping the string intact
所以现在我的子字符串结果是:
This is my string with a special char : &egra
但我想要这样的东西:
This is my string with a special char : è
我认为您必须使用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
中是否有与符。如果相应的分号出现在byteX
或更高版本,请在分号之后而不是byteX
之后剪切字符串
但是,如果您愿意预处理字符串,Mike的解决方案将更加准确,因为他将字符串切割为X
个字符,而不是字节。最好的解决方案是将文本存储为UTF-8,而不是将其存储为HTML实体。除此之外,如果您不介意计数被关闭(&grave;
等于一个字符,而不是7),那么下面的代码段应该可以工作:
<?php
$string = 'This is my string with a special char : è - and I want it to cut in the middle of the "è" 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 : è - and I want it to cut in the middle of the "è" 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') === 'é'
// should be 'é '
当字符串采用多字节编码时,必须在拆分之前将所有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,它本身不是