Perl 非贪婪正则表达式匹配超出应有的范围

Perl 非贪婪正则表达式匹配超出应有的范围

我有以下文本,需要从中删除一些wdiff输出。

text='Иса Мәсіхтің елшісі Петірден [-(-] осы күнәкар дүниеде [-)-] жат жерлік болып, Понти, Ғалатия, [-Қападоқия, Азия және Бітүния аймақтарында шашыраған [ сенушілерге дұғай сәлем ].-] {+Қападоқия… https://t.co/.......... [Петірдің 1 1:1-5]+}'

我正在尝试使用[- -]非贪婪的 perl regex 删除文本块\[-.*?-\],但它也与之前的块匹配:

$ perl -pe 's|\[-.*?-\] {\+(\S+… https://t.co/.*)\+}|\1|' <<<"$text"
Иса Мәсіхтің елшісі Петірден Қападоқия… https://t.co/.......... [Петірдің 1 1:1-5]

预期输出:

$ perl -pe 's|\[-.*?-\] {\+(\S+… https://t.co/.*)\+}|\1|' <<<"$text"
Иса Мәсіхтің елшісі Петірден [-(-] осы күнәкар дүниеде [-)-] жат жерлік болып, Понти, Ғалатия, Қападоқия… https://t.co/.......... [Петірдің 1 1:1-5]

答案1

我已将您的输入字符串简化为qABxBCzABxBCDEFw, 其中

A represents [
B represents -
C represents ]
D represents {\+
E represents the text between the +s (including the URL)
F represents \+}
Lower case letters represent everything else.

因此,这里有一些针对输入运行的替代命令:

                                  Command                          Output
0. Input text:                                                     qABxBCzABxBCDEFw
1. Non-greedy:                   's|AB.*?BCD(E)F|\1|'              qEw
2. Greedy:                       's|AB.*BCD(E)F|\1|'               qEw
3. Restricted Non-greedy:        's|AB[^B]*?BCD(E)F|\1|'           qABxBCzEw
4. Restricted Greedy:            's|AB[^B]*BCD(E)F|\1|'            qABxBCzEw
5. Constrained Non-greedy:       's|(.*)AB.*?BCD(E)F|\1\2|'        qABxBCzEw
6. Constrained Greedy:           's|(.*)AB.*BCD(E)F|\1\2|'         qABxBCzEw

命令 1 是您尝试过的命令。命令 2 是同样的事情,但不是非贪婪的。如您所知,它们产生相同的结果。

在我看来,非贪婪仅适用于长度的文本与类似的内容匹配.*。  不影响起点。  正则表达式匹配总是尽快开始。所以,当你说AB.*?BC(ie, \[-.*?-\]) 时,它匹配第一的 [-在线上。然后,您期望它匹配以 结尾的任何字符的最短可能字符串-]。您可能期望这会是[-(-]。但仔细观察:正则表达式是AB.*?BCD(E)F,因此它必须匹配以 结尾的任何字符的最短可能字符串-] {+。这迫使它消耗几乎直到 URL 的所有内容。

我已经编写了四个替代命令,它们似乎可以满足您的要求。 “受限”的(3 和 4)搜索的不是AB.*BC,而是AB[^B]*BC;用文字来说,AB…… “……”中BC没有s。B在你的例子中,这意味着[-…… “……”中-]没有s。 -“受限”者(5 和 6)通过在它们前面AB.*BC放置一个贪婪者来迫使比赛尽可能晚地开始。.*事实证明,你AB.*BC在这些方面是否贪婪或非贪婪并不重要。

答案2

你必须使用一个消极环视:

perl -pe 's|\[-((?!-\]).)*-\] {\+(\S+… https://t.co/.*)\+}|\2|' <<<$text

问题是第一次出现[-匹配。那么该模式的非贪婪并没有达到预期的效果,无论它多么非贪婪。使用否定环视,您可以匹配除 string 之外的所有内容-],然后它仅匹配该部分之前的出现{+...+}

相关内容