这个功能在php输出页面的时候很常用 ,就是把一个字符串截取为不大于某个长度的字符串。本身是很简单的事情,但是附加了一些需求:1,字符串中含有中文,也就是单字节双字节混着的。2,字符串中含有html代码。
对于中文截取,网上有现成的代码可以拿来用,就像这样:
function
trunk(
$str
,
$most
,
$append
=
"
...
"
) {
if
(
strlen
(
$str
)
<=
$most
) {
return
$str
; }
return
substr_cut(
$str
,
$most
-
strlen
(
$append
))
.
$apend
; }
function
substr_cut(
$str_cut
,
$length
){
if
(
strlen
(
$str_cut
)
>
$length
){
for
(
$i
=
0
;
$i
<
$length
;
$i
++
)
if
(
ord
(
$str_cut
[
$i
])
>
128
)
$i
++
;
$str_cut
=
substr
(
$str_cut
,
0
,
$i
); }
return
$str_cut
; }
这里就是简单的判断一下字节是否大于128,是就往前多移一位。因为对于GB2312编码,凡双字节第一个字节都是大于128的。
至于第二个需求,含有html代码的,其实我觉得这样的要求通过css来做更加合适了。
通过设置width,height,line-height限定其块大小后,再设定overflow : hidden ;就可以做到了。如果只为IE而做的话,那么有更多的CSS手段来控制超出边界后的处理。
如果一定要自己写程序处理的话,我想最好是只处理简单情况,如果仅为了截取含html代码的字符串就要写一个完全的html parser的话,未免太小题大作了。这里我写了一段仅处理成对、非嵌套情况的:
function
trunkhtml(
$str
,
$most
,
$append
=
"
...
"
) {
$arr
=
preg_split
(
"
/(<[^>]*>)/
"
,
$str
,-
1
,
PREG_SPLIT_DELIM_CAPTURE
|
PREG_SPLIT_OFFSET_CAPTURE);
$istag
=
FALSE
;
$notagstr
=
""
;
foreach
(
$arr
as
$v
) {
if
(
!
$istag
)
$notagstr
.=
$v
[
0
];
$istag
=
!
$istag
; }
if
(
strlen
(
$notagstr
)
<=
$most
) {
return
$str
; }
$str_cut
=
substr_cut(
$notagstr
,
$most
-
strlen
(
$append
));
$cut_len
=
strlen
(
$str_cut
);
$istag
=
FALSE
;
foreach
(
$arr
as
$i
=>
$v
) {
if
(
!
$istag
) {
$len
=
strlen
(
$v
[
0
]);
if
(
$cut_len
>
$len
)
$cut_len
-=
$len
;
else
{
$pos
=
$v
[
1
]
+
$cut_len
;
if
(
$i
%
4
==
0
) {
return
substr
(
$str
,
0
,
$pos
)
.
$append
; }
else
{
$ret
=
substr
(
$str
,
0
,
$pos
)
.
$append
;
if
(
isset
(
$arr
[
$i
+
1
]))
$ret
.=
$arr
[
$i
+
1
][
0
];
return
$ret
; } } }
$istag
=
!
$istag
; }
assert
(
FALSE
);
return
$str_cut
; }
这里做法也不复杂,先用正则把它分割开来,取出不在<>中的部分拼在一起,先用前面的substr_cut截取一次,记住最终截了多长。然后再用各个部分长度去减,减到不够的时候就确定是截在哪个位置了。因为假定html标签都是成对的,最后再判断一下是否处在一对标签中。