我正在尝试让ColdFusion的REFindNoCase函数返回匹配字符串的多个实例,但似乎无法使其工作:
<cfset string2test="cfid skldfjskdl cfid sdlkfjslfjs cftoken dslkfjdslfjks cftoken">
<cfset CookieCheck = REFindNoCase( 'CFTOKEN', string2test, 1, true)>
<cfif arrayLen( CookieCheck['LEN'] ) gt 1>
MULTIPLE CFTOKEN!
</cfif>
我需要使用正则表达式魔术语法来搜索多于1个?
答案 0 :(得分:2)
上面代码的语法将创建带有数组(LEN,POS)的结构,用于模式匹配和子表达式。 RegEx子表达式在模式中的括号内。 'CFTOKEN'模式不包含子表达式。
我认为REFindNoCase不会做你想要完成的事情。
例如,如果您使用'。*?(cftoken)'作为模式:
<cfset CookieCheck = REFindNoCase('.*?(CFTOKEN)', string2test, 1, true)>
(CFTOKEN)是一个子表达式。如果删除“?”,则返回最后一次'cftoken'的信息。
第一个数组项中的值将匹配整个模式,直到第一个'cftoken'(字符串的前40个字符)。第二组值将标识在第一场比赛中找到的'cftoken'字符串(前40个字符)。
因为示例中的语句不包含子表达式,所以只返回第一个模式匹配。
如果您需要检查是否多次列出某些内容,或者您不需要操作原始字符串,我建议您使用REMatchNoCase()。它返回一组模式匹配但没有位置信息。
答案 1 :(得分:1)
您可以创建一个自定义方法来循环遍历字符串,并将每个匹配项放入一个数组(或结构,或任何您想要的)。以下是我如何处理它的一个例子:
<cfscript>
public array function reFindMatches(required string regex, required string str) {
var start = 1;
var result = [];
var matches = [];
var match = '';
do {
matches = ReFind(arguments.regex, arguments.str, start, true);
if ( matches.pos[1] ) {
match = matches.len[1] ? Mid(arguments.str, matches.pos[1], matches.len[1]) : '';
ArrayAppend(result, match);
start = matches.pos[1] + matches.len[1];
}
} while(matches.pos[1]);
return result;
}
testString = 'cfid skldfjskdl cfid sdlkfjslfjs cftoken dslkfjdslfjks cftoken';
regex = '(?i)(\bcftoken\b)';
check = reFindMatches(regex=regex, str=testString);
WriteDump(var=check);
</cfscript>
我包含的示例正则表达式以(?i)
开头,表示搜索不区分大小写。所以,没有必要调用ReFindNoCase
...你可以直接传入你想要使用的正则表达式。
上面的代码应该输出一个包含两个元素的数组,其中包含单词 cftoken 。
答案 2 :(得分:0)
如果您需要来计算有多少个实例,请使用rematch(或rematchNoCase)。
如果你需要的只是来确定是否有多个,你可以这样做:
<cfset FirstInstance = refindNoCase( 'cftoken' , string2test ) />
<cfif FirstInstance AND refindNoCase( 'cftoken' , string2test , FirstInstance+7 ) >
... more than one instance ...
</cfif>
这可能比使用子表达式或循环多次重新匹配更有效。
根据相关数据,可能更有效地执行以下操作:
<bfif string2text.indexOf('cftoken') NEQ string2text.lastIndexOf('cftoken') >
(即,如果您知道其他实例总是在字符串末尾附近,而最初的实例则不是。)