以下是使用jSoup HTML 解析器的方法:
<cfset jsoup = createObject('java','org.jsoup.Jsoup') />
<cfset Dom = jsoup.parse( InputHtml ) />
<cfset Dom.select('a[href]').attr('href','{replaced}') />
<cfset NewHtml = Dom.html() />
(在 CF9 和更早版本上,这需要将 jsoup 的 jar 放在 CF 的 lib 目录中,或者使用JavaLoader。)
使用 HTML 解析器通常比使用正则表达式更好,尤其是因为它更易于维护和理解。
这是使用正则表达式的一种不完美的方法:
<cfset NewHtml = InputHtml.replaceAll
( '(?<=<a.{0,99}?\shref\s{0,99}?=\s{0,99}?)(?:"[^"]+|''[^'']+)(["'])'
, '$1{replaced}$1'
)/>
这有望证明为什么使用诸如jsoup之类的工具绝对是要走的路……
(顺便说一句,上面使用的是 Java 正则表达式引擎(通过string.replaceAll),因此它可以使用 CF 的内置正则表达式(rereplace/rematch/etc)中不存在的lookbehind 功能)
更新,基于您提供的新代码示例...
这是一个如何使用 jsoup 来完成您正在做的事情的示例 - 它可能仍需要一些更新(取决于 {clickurl} 最终将要做什么),但它目前的功能与您的示例代码尝试的功能相同:
<cfset jsoup = createObject('java','org.jsoup.Jsoup') />
<cfset links = jsoup.parse( Arguments.HtmlCode )
<!--- select all links beginning http and change their href --->
.select('a[href^=http]').attr('href',' {clickurl}')
<!--- get HTML for all links, then split into array. --->
.outerHtml().split('(?<=</a>)(?!$)')
/>
<cfdump var=#links# />
中间部分都是一个 cfset,但为了清楚起见,我将其拆分并添加了注释。(如果您愿意,当然可以使用多个变量和 3 个以上的 cfset 来执行此操作。)
Again, it's not a regex, because what you're doing involves parsing HTML, and regex is not designed for parsing tag-based syntax, so isn't very good at it - there are too many quirks and variations with HTML and describing them in a single regex gets very complicated very quickly.