假设您有以下字符串:Hello... how are you!!?? I'm bored!!
我希望尽可能删除背对背的标点符号,并在类似“!?”的情况下保留问号。过滤后的字符串应如下所示:
Hello. how are you? I'm bored!
最佳答案是解决此问题的最简洁的解决方案。我希望正则表达式是解决这个问题的最好方法,但我对正则表达式的了解非常非常有限,而且我不知道如何解决这个问题。不过,我对非正则表达式解决方案更加满意!对你提供的任何代码的解释 - 除非非常简单 - 也会很好。
谢谢!
答案 0 :(得分:3)
$str = preg_replace('~[?!]{2,}~', '?', preg_replace('~([.,!?])(\\1+)~', '\\1', $str));
或在一次preg_replace
电话中(感谢Alix Axel)
$str = preg_replace(array('~([.,!?])(\\1+)~', '~[?!]{2,}~'), array('\\1', '?'), $str);
只需枚举大括号中你所关注的所有标点符号
UPD :处理!?
只是将其与另一个正则表达式嵌套
解释一切意味着什么:
preg_replace('~([.,!?])(\\1+)~', '\\1', $str)
表达式([.,!?])(\\1+)
表示 - 只有在.,!?
前面至少有一个相同的字符\\1+
时才会找到\\1
,其中+
- 是对前一个字符的引用匹配,at least one
为[?!]{2,}
。
用仅一个字符替换所有这些。
外部表达式find all ? or ! if they are at least 2 in a row
表示?
,并将其替换为{{1}}
答案 1 :(得分:1)
你可以使用preg_replace:
$a="Hello... how are you!!?? Im bored!!!!!!"; echo preg_replace("/([.!?])+/iS","$1",$a);
=> Hello. how are you? Im bored!
答案 2 :(得分:0)
$string = "Hello... how are you!!?? I'm bored!!"
$new_string = $string;
foreach(array('.',',','?','!') as $value) {
$i = ;
do {
$prev_string = $new_string;
$string = str_replace($value . $value,$value,$string;
$i++;
} while ($string !== $prev_string && $i<100)
}
那摆脱了重复,但没有?!?。
我认为第二种解决方案可行,保留“坏人”的第一位。 如果你想保留最后一个,那么也有解决方案。
<?php
$string = str_split($string);
$new_string = array();
$i = 0;
foreach($string as $key => $char) {
echo 'Processing: ' . $char . '<br />';
$prev_key = $key - 1;
$prev_char = $string[$prev_key];
if($i!== 0) {
if(in_array($char,$bad_chars) && in_array($prev_char,$bad_chars) ) {
// do nothing
} else {
$new_string[] = $char;
}
} else {
$prev_char = $char;
$new_string[] = $prev_char;
}
$i++;
}
$string = implode('',$string);
$new_string = implode('',$new_string);
?><br />
<?php echo $string; ?><br />
<?php echo $new_string; ?><br />