-1

我找到了一些部分帮助,但似乎无法完全完成我所需要的。我需要能够执行以下操作:

我需要一个正则表达式来用匹配任何表达式替换两个长于 3 个字符的单词之间的任何 1 到 3 个字符的单词:

例如:

walk to the beach ==> walk(.*)beach

如果 1 到 3 个字符的单词前面没有超过 3 个字符的单词,那么我想将该 1 到 3 个字母的单词翻译成'<word> ?'

例如:

on the beach ==> on ?the ?beach

规则越简单越好(当然,如果有更复杂的替代版本,性能更高,那么我会采用它,并且我最终预计最终会大量使用)。

这将在最有可能与preg_replace. 因此,如果你能把它放在那个上下文中,那就更好了!

到目前为止,我得到了以下信息:

$string = preg_replace('/\s+/', '(.*)', $string); 
$string = preg_replace('/\b(\w{1,3})(\.*)\b/', '${1} ?', $string);

但这会导致:

walk to the beach ==> 'walk(.*)to ?beach' 

这不是我想要的。'on the beach'似乎翻译正确。

4

1 回答 1

-2

我认为您将需要两个替代品。让我们从第一个要求开始:

$str = preg_replace('/(\w{4,})(?: \w{1,3})* (?=\w{4,})/', '$1(.*)', $str);

当然,您需要将那些\w(匹配字母、数字和下划线)替换为您真正想要视为单词字符的字符类。

第二个更难一些,因为匹配不能重叠,并且lookbehinds不能是可变长度的。所以我们必须在一个循环中运行多次:

do
{
    $str = preg_replace('/^\w{0,3}(?: \w{0,3})* (?!\?)/', '$0?', $str, -1, $count);
} while($count);

在这里,我们匹配从字符串开头开始的所有内容,只要它只是由空格分隔的最多 3 个字母的单词,再加上一个尾随空格(仅当它后面没有 a 时?)。然后我们将所有这些放回原处,并附加一个?.

更新:

在评论中进行了所有讨论之后,这是一个更新的解决方案。

运行第一行后,我们可以假设剩下的少于 3 个字母的单词将位于字符串的开头或结尾。所有其他人都将被折叠到(.*). 由于您想在 之间添加所有空格?,因此您甚至不需要循环(实际上这些是剩下的唯一空格):

$str = preg_replace('/ /', ' ?', $str);

(在我的第一行代码之后立即执行此操作。)

这将给出以下两个结果(结合第一行):

let us walk on the beach now go => let ?us ?walk(.*)beach ?now ?go
let us walk on the beach there now go => let ?us ?walk(.*)beach(.*)there ?now ?go
于 2012-10-27T22:47:49.553 回答