正则表达式替换文本但在文本位于特定标记之间时排除

Wer*_*eri 10 regex

我有以下字符串:

Lorem ipsum Test dolor sit amet, consetetur sadipscing elitr, sed diam nonumy <a href="http://Test.com/url">Test</a> eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd sed Test dolores et ea rebum. Stet clita kasd gubergren, no sea <a href="http://url.com">Test xyz</a> takimata sanctus est Lorem ipsum dolor sit amet.
Run Code Online (Sandbox Code Playgroud)

现在我将标签之外的字符串'Test'替换为不在标签之间(例如替换为'1234').

Lorem ipsum 1234 dolor sit amet, consetetur sadipscing elitr, sed diam nonumy <a href="http://Test.com/url">Test</a> eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd sed 1234 dolores et ea rebum. Stet clita kasd gubergren, no sea <a href="http://url.com">Test xyz</a> takimata sanctus est Lorem ipsum dolor sit amet.
Run Code Online (Sandbox Code Playgroud)

我从这个正则表达式开始: (?!<a[^>]*>)(Test)([^<])(?!</a>)

但是有两个问题没有解决:

  1. 文本'Test'也被替换为Tags(例如)
  2. 标签之间的文本是否与搜索到的文本不完全匹配,它也会被替换(例如<a href="http://Test.com/url">)

我希望有人有解决方案来解决这个问题.

Ada*_*dam 12

回答

使用

(Test)(?!(.(?!<a))*</a>)
Run Code Online (Sandbox Code Playgroud)

说明

让我提醒你一些符号的含义:

1)?!是一个负前瞻,例如r(?!d)选择所有r不直接跟随的d:

在此输入图像描述

2)因此,如果没有角色,永远不要开始消极的前瞻.只是(?!d)毫无意义:

在此输入图像描述

3)?可以用作懒人比赛.例如,.+E会选择

123EEE

整个字符串123EEE.但是,根据需要.+?E选择尽可能少的"任何字符"(.+).它只会选择123E.

回答:

Protist的答案是你应该使用(?!<a[^>]*?>)(Test)(?![^<]*?</a>).让我解释一下如何缩短它.

如2)所述,在比赛前进行前瞻是毫无意义的.所以以下相当于原始人的答案:

(Test)(?![^<]*?</a>)
Run Code Online (Sandbox Code Playgroud)

也是因为<不允许,懒惰的比赛?是多余的,所以它也相当于

(Test)(?![^<]*</a>)
Run Code Online (Sandbox Code Playgroud)

这将选择所有Test未后跟</a>不带符号<的内容.这就是为什么在任何之前或之后出现的测试<a ...> .. </a>将被替换的原因.

但请注意

Lorem Test dolor <a href="http://Test.com/url">Test <strong>dolor</strong></a> eirmod
Run Code Online (Sandbox Code Playgroud)

会变成

Lorem 1234 dolor <a href="http://1234.com/url">1234 <strong>dolor</strong></a> eirmod 
Run Code Online (Sandbox Code Playgroud)

为了抓住你可以改变你的正则表达式

(Test)(?!(.(?!<a))*</a>)
Run Code Online (Sandbox Code Playgroud)

执行以下操作:

选择每一个字Test后面没有一个字符串***</a>,其中每个字符***后面没有<a.

注意点.是重要的(见2)).

请注意,懒惰匹配(Test)(?!(.(?!<a))*?</a>)不相关,因为嵌套链接在HTML4和HTML5中是非法的(如同<a href="#">..<a href="#">...</a>..</a>).

原始人说

此外,不建议在原始HTML上使用正则表达式.

我同意这一点.问题是如果标签未关闭或打开会导致问题.例如,这里提到的所有解决方案都会改变

Lorem Test dolor Test <strong>dolor</strong></a> eirmod
Run Code Online (Sandbox Code Playgroud)

Lorem Test dolor Test <strong>dolor</strong></a> eirmod 1234 dolores sea 1234 takimata 
Run Code Online (Sandbox Code Playgroud)


pro*_*ist 11

(?!<a[^>]*?>)(Test)(?![^<]*?</a>)
Run Code Online (Sandbox Code Playgroud)

与zb226相同,但使用惰性匹配进行了优化

此外,不建议在原始HTML上使用正则表达式.


zb2*_*226 6

这应该可以解决问题:

(?!<a[^>]*>)(Test)(?![^<]*</a>)
Run Code Online (Sandbox Code Playgroud)

自己在 regexr 上尝试一下

后续:正如Adam上面所解释的,第一部分没有任何作用,可以完全删除:

(Test)(?![^<]*</a>)
Run Code Online (Sandbox Code Playgroud)