不要在双方括号之间的任何位置选择文本

时间:2019-04-02 15:00:47

标签: php regex pcre

我需要编写一个正则表达式,该正则表达式可以根据模式匹配某些东西(并且可以工作),但是如果文本在双方括号内的任何地方,则不应与之匹配。 实际的问题是,后面的负向后视不能是可变长度。

情况是:

  • 有一个短语词典。
  • 单词多的短语比单词短的短语具有更高的“优先级” /获得优先级。
  • 某些短语是其他较长短语的一部分。

字典示例(在实际代码中按数组排序):

Wooden House
House
Wooden

要解析的示例文本:

Lorem ipsum Wooden House dolor sit amet

要解析的文本是通过preg_replace来解析的,方法是遍历字典并添加[[randomstaff-_-current dictionary phrase]],例如:

Lorem ipsum Wooden House dolor sit amet-> Lorem ipsum [[randomstuff-_-Wooden House]] dolor sit amet

当前,在第二次迭代后,它变为: Lorem ipsum [[randomstuff-_-Wooden House]] dolor sit amet-> Lorem ipsum [[randomstuff-_-Wooden[[randomstuff-_-House]]]]

,如果它已经在[[]]之间,我希望保持不变。

因此,基本上,如果[[]]之间的匹配在任何地方 -忽略它。

$dictPhrases = ["Wooden House", "House", "Wooden"];
$TEXT = "Lorem ipsum Wooden House dolor sit amet";

for ($dictPhrases as $phrase){
 $phraseOccurences = 0; //irrelevant in this example
 $TEXT = preg_replace("/(?i)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)/", "[[$randomstuff-_-" . $phrase . "]]", $TEXT, -1, $phraseOccurences);

}

问题是如何更改:

/(?i)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)/

变成这样:

/(?i)(?<!\[\[.*)(?<= |^|\n)(" . $phrase. "[&()'-]{0,1})(?= |$|\.|\,)(?!.*\]\])/

查看匹配的短语是否不在[[]]之间,如果匹配,则将其丢弃。

2 个答案:

答案 0 :(得分:0)

只需变换

["Wooden House", "House", "Wooden"]

转换为单个正则表达式:

"(?:Wooden House|House|Wooden)"

然后将其放入主正则表达式中。

尝试如下所示:

$dictPhrases = ["Wooden House", "House", "Wooden"];
$TEXT = "Lorem ipsum Wooden House dolor sit amet";

$pattern = "/(?i)(?<= |^|\n)((?:" . join('|', $dictPhrases) . ")[&()'-]{0,1})(?= |$|\.|\,)/";

$phraseOccurences = preg_match_all($pattern, $TEXT);
$TEXT = preg_replace($pattern, "[[$randomstuff-_-$1]]", $TEXT);

Here正则表达式演示。

Here一个PHP演示。

答案 1 :(得分:0)

大概有两种解决方案。

1)获取比赛的开始位置,在子字符串(0,比赛的第一个字符)中找到所有“ [[”和“]]”,并将其修改为2。 2)获取匹配的起始位置,获取子串(0,匹配的第一个字符)中“ [[”和最后一个“]]”的最后位置,并检查哪个更接近。

两者都应在括号不能嵌套的假设下工作(在这种情况下确实如此)。 不幸的是,所需的代码超出了正则表达式的功能。

我将在星期一尝试实现它,并为将来的搜索者发布最终代码-如果它可以按预期的方式工作。