【问题标题】:Find Multiple Occurrences in String using REFind使用 REFind 查找字符串中的多次出现
【发布时间】:2013-09-10 19:39:37
【问题描述】:

我正在尝试让 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 个吗?

【问题讨论】:

    标签: coldfusion coldfusion-10


    【解决方案1】:

    上述代码的语法将创建带有数组 (LEN,POS) 的结构,用于模式匹配和子表达式。 RegEx 子表达式在模式的括号内。 'CFTOKEN' 模式不包含子表达式。

    我不认为 REFindNoCase 会做你想要完成的事情。

    例如,如果您使用 '.*?(cftoken)' 作为模式:

    <cfset CookieCheck =  REFindNoCase('.*?(CFTOKEN)', string2test, 1, true)>
    

    (CFTOKEN) 是一个子表达式。如果删除“?”,则返回最后一次出现 'cftoken' 的信息。

    第一个数组项中的值将匹配整个模式,直到第一个“cftoken”(字符串的前 40 个字符)。第二组值将标识在第一次匹配中找到的“cftoken”字符串(前 40 个字符)。

    因为示例中的语句不包含子表达式,所以只返回第一个模式匹配。

    如果您需要检查某些内容是否被多次列出,或者您不需要操作原始字符串,我建议使用 REmatchNoCase()。它返回一个模式匹配数组,但没有位置信息。

    【讨论】:

    • 这就是我所需要的!现在它返回多个匹配项!
    【解决方案2】:

    您可以创建一个自定义方法来循环字符串,并将每个出现的地方放入一个数组(或结构,或任何您想要的)中。这是我可能如何处理它的一个示例:

    <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

    【讨论】:

    • 循环是我目前的解决方案,看起来 REFind + Subexpressions 更优雅/更简单,但我无法理解为什么它不能按预期工作。
    【解决方案3】:

    如果您需要计算有多少个实例,请使用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') >
    

    (即,如果您知道其他实例总是靠近字符串的末尾,而初始实例则不是。)

    【讨论】:

      猜你喜欢
      • 2017-05-08
      • 2011-04-21
      • 2021-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-21
      • 2013-09-26
      相关资源
      最近更新 更多