有一个输入字符串:
$subject = "This punctuation! And this one. Does n't space that one."
我还有一个数组,其中包含我希望执行的替换的异常,目前只有一个成员:
$exceptions = array(
0 => "n't"
);
我想实现这个复杂的解决方案的原因是这个数组将来会被扩展,可能包含数百个成员。
我想在单词边界插入空白(重复的空白将在稍后删除)。然而,某些界限应该被忽略。例如,上面句子中的感叹号和句号应该用空格包围,但撇号不应该。一旦使用trim(preg_replace('/s+/', ' ', $subject));
从最终结果中删除了重复的空白,它应该看起来像这样:
"This punctuation ! And this one . Does n't space that one ."
我正在研究如下解决方案:
使用
preg_match('b', $subject, $offsets, 'PREG_OFFSET_CAPTURE');
收集可以插入空格的索引数组遍历
$offsets
数组
- 将
$subject
从当前偏移量之前的空白分割到下一个空白或行尾。 - 检查结果是否包含在
$exceptions
数组中。 - 如果异常数组中不包含分割结果,则在当前偏移量处插入空白字符。
到目前为止,我有以下代码:
$subject="This punctuation! And this one. Does n't space that one.";
$pattern = '/b/';
preg_match($pattern, $subject, $offsets, PREG_OFFSET_CAPTURE );
if(COUNT($offsets)) {
$indexes = array();
for($i=0;$i<COUNT($offsets);$i++) {
$offsets[$i];
$substring = '?';
// Replace $substring with substring from after whitespace prior to $offsets[$i] until next whitespace...
if(!array_search($substring, $exceptions)) {
$indexes[] = $offsets[$i];
}
}
// Insert whitespace character at each offset stored in $indexes...
}
我找不到一个合适的方法来创建$substring
变量来完成上面的例子。
$res = preg_replace("/(?:n't|ALL EXCEPTIONS PIPE SEPARATED)(*SKIP)(*F)|(?!^)(?<!h)b(?!h)/", " ", $subject);
echo $res;
输出:
This punctuation ! And this one . Doesn't space that one .
演示,解释
One "(但不一定快,取决于你有多少异常)解决方案是首先用不包含任何标点符号的唯一字符串替换字符串中的所有异常,然后执行替换,然后将唯一替换字符串转换回原始版本。
下面是一个使用md5
的例子(但可以是很多其他的东西):
$subject = "This punctuation! And this one. Doesn't space that one.";
$exceptions = ["n't"];
foreach ($exceptions as $exception) {
$result = str_replace($exception, md5($exception), $subject);
}
$result = preg_replace('/[^a-z0-9s]/i', ' ', $result);
foreach ($exceptions as $exception) {
$result = str_replace(md5($exception), $exception, $result);
}
echo $result; // This punctuation ! And this one . Doesn't space that one .