我正在学习如何在Coldfusion中创建一个REGEX,它将扫描大量的html文本并创建一个项目列表。
我想要的项目包含在以下
之间<span class="findme">The Goods</span>
感谢您提供任何建议。
答案 0 :(得分:6)
你没有说什么版本的CF.从v8开始,您可以使用REMatch来获取数组
results = REMatch('(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>', text)
使用ArrayToList将其转换为列表。 对于旧版本,使用REFindNoCase并使用Mid()来提取子字符串。
编辑:为了回答你的后续评论,使用REFind返回所有匹配的过程非常复杂,因为该函数只返回FIRST匹配。这意味着你每次都必须多次调用REFind传递一个新的startpos。 Ben Forta已经编写了一个UDF,它可以完成这项工作并为您节省一些时间。
<!---
Returns all the matches of a regular expression within a string.
NOTE: Updated to allow subexpression selection (rather than whole match)
@param regex Regular expression. (Required)
@param text String to search. (Required)
@param subexnum Sub-expression to extract (Optional)
@return Returns a structure.
@author Ben Forta (ben@forta.com)
@version 1, July 15, 2005
--->
<cffunction name="reFindAll" output="true" returnType="struct">
<cfargument name="regex" type="string" required="yes">
<cfargument name="text" type="string" required="yes">
<cfargument name="subexnum" type="numeric" default="1">
<!--- Define local variables --->
<cfset var results=structNew()>
<cfset var pos=1>
<cfset var subex="">
<cfset var done=false>
<!--- Initialize results structure --->
<cfset results.len=arraynew(1)>
<cfset results.pos=arraynew(1)>
<!--- Loop through text --->
<cfloop condition="not done">
<!--- Perform search --->
<cfset subex=reFind(arguments.regex, arguments.text, pos, true)>
<!--- Anything matched? --->
<cfif subex.len[1] is 0>
<!--- Nothing found, outta here --->
<cfset done=true>
<cfelse>
<!--- Got one, add to arrays --->
<cfset arrayappend(results.len, subex.len[arguments.subexnum])>
<cfset arrayappend(results.pos, subex.pos[arguments.subexnum])>
<!--- Reposition start point --->
<cfset pos=subex.pos[1]+subex.len[1]>
</cfif>
</cfloop>
<!--- If no matches, add 0 to both arrays --->
<cfif arraylen(results.len) is 0>
<cfset arrayappend(results.len, 0)>
<cfset arrayappend(results.pos, 0)>
</cfif>
<!--- and return results --->
<cfreturn results>
</cffunction>
这为您提供了每个匹配的开始(pos)和长度,以便让每个子字符串使用另一个循环
<cfset text = '<span class="findme">The Goods</span><span class="findme">More Goods</span>' />
<cfset pattern = '(?i)<span[^>]+class="findme"[^>]*>(.+?)</span>' />
<cfset results = reFindAll(pattern, text, 2) />
<cfloop index="i" from="1" to="#ArrayLen(results.pos)#">
<cfoutput>match #i#: #Mid(text, results.pos[i], results.len[i])#<br></cfoutput>
</cfloop>
编辑:使用subexnum参数更新了reFindAll。将其设置为2将捕获第一个子表达式。默认值1捕获整个匹配。
答案 1 :(得分:2)
尝试研究使用常规DOM Parser进行HTML工作并通过XPath查询它的可能性,而不是通过基于正则表达式的憎恶来解决这个问题。
<cfset dom = XmlParse(scrubbedHtml, true)>
<cfset result = XmlSearch(dom, "//span[@class='findme']")>
完成。
编辑:Coldfusion的XmlSearch()
没有很好的XML命名空间支持。如果最终生成XHTML而不是更推荐的XML,请使用以下XPath(请注意冒号)"//:span[@class='findme']"
或"//*:span[@class='findme']"
。有关详细信息,请参阅here和here。
有关jTidy可以执行的操作的完整概述,请参阅jTidy API documentation。