【问题标题】:Parse a specific variable from a url stored as a string with CFML从使用 CFML 存储为字符串的 url 中解析特定变量
【发布时间】:2012-04-30 12:54:22
【问题描述】:

我想从存储为字符串的 url 中解析特定的 url 变量键值。看来您可以在 ACF 下使用底层的 java 库 Coldfusion.util.HTMLTools,但我也需要它在 Railo 下工作。还有另一种方法,还是使用正则表达式是最好的答案?

我正在尝试检索没有锚点的 url 变量键的值,格式如下例所示。 http://example.com?key=134324625625435#gid=0

【问题讨论】:

    标签: coldfusion railo


    【解决方案1】:

    我发布了对斯科特答案的评论,但它太长了,所以......

    约翰写道:

    运行以下示例,我最终得到的值为 0, 但我认为它应该是整个键值?

    <cfoutput>
        <cfset theUrl = "https://docs.google.com/spreadsheet/ccc?key=0AthiZNZ73LBndUzRTUkplbmNhYWc##gid=0" />
        <cfset theUrl = listRest(theUrl, "?")>
        <cfloop list="#theUrl#" index="URLPiece" delimiters="&">
            Key: #listFirst(urlPiece, "=")# Value: #listLast(urlPiece, "=")# <br />
        </cfloop>
    </cfoutput>
    

    该示例 URL 失败的原因是它包含一个页面段(哈希后的位),需要在解析查询字符串之前将其剥离。

    通过将键/值部分包装在UrlDecode 中来获取正确的变量/值也很重要。

    另外,值中有一个等号是完全可以接受的,所以?key== 应该返回= 作为值,这意味着将ListLast 更改为ListRest 并将includeEmptyFields 设置为true .

    另外,如果您有一个查询字符串,例如 ?a&amp;b,那么约定是将值设置为 true 或空字符串 - 当前代码设置为键名,这是错误的。

    总而言之,这是一个函数:

    <cffunction name="getParamsFromUrlString" returntype="Struct" output=false >
        <cfargument name="UrlString" type="String" required />
        <cfargument name="Separator" type="String" default="?" />
        <cfargument name="Delimiter" type="String" default="&" />
        <cfargument name="AssignOp"  type="String" default="=" />
        <cfargument name="EmptyVars" type="String" default="" />
    
        <cfset var QueryString = ListRest( ListFirst( Arguments.UrlString , '##' ) , Arguments.Separator ) />
        <cfset var Result = {} />
    
        <cfloop index="local.QueryPiece" list=#QueryString# delimiters="#Arguments.Delimiter#">
    
            <cfif NOT find(Arguments.AssignOp,QueryPiece)>
                <cfset Result[ UrlDecode( QueryPiece ) ] = Arguments.EmptyVars />
            <cfelse>
                <cfset Result[ UrlDecode( ListFirst(QueryPiece,Arguments.AssignOp) ) ]
                    =  UrlDecode( ListRest(QueryPiece,Arguments.AssignOp,true) ) />
            </cfif>
        </cfloop>
    
        <cfreturn Result />
    </cffunction>
    

    可以这么简单地使用:

        <cfset theUrl = "https://docs.google.com/spreadsheet/ccc?key=0AthiZNZ73LBndUzRTUkplbmNhYWc##gid=0" />
        <cfset Data = getParamsFromUrlString( theUrl ) />
        <cfdump var=#Data# />
    

    或者它可以用于复杂的非标准 URL 字符串,如下所示:

        <cfset theUrl = "https://somewhere/index.jsp;x:145;y:54;z:1;f;d:%23%23;w:%3B" />
        <cfset Data = getParamsFromUrlString( theUrl , ';' , ';' , ':' , 'true' ) />
        <cfdump var=#Data# />
    

    以及(希望)介于两者之间的一切。

    【讨论】:

      【解决方案2】:

      刚刚重新阅读了这个问题,如果您只处理一个特定的变量,您可以使用简单的正则表达式轻松做到这一点:

      <cfset Value = rematch( '[?&]key=[^&##]+' , TheUrl ) />
      <cfset Value = UrlDecode( ListRest( Value[1] , '=' , true ) ) />
      

      (如果您需要更通用的解决方案,其他答案当然仍然有用。)

      【讨论】:

      • 我认为 rematch() 的参数是错误的(参数排序在 CFML 中很少直观)
      • 好吧,您对排序是正确的(doh; 已修复),但在很少直观的情况下是不正确的 - 它并不完美,但也不可怕。
      • 也许“很少直观”有点刺耳,但充其量是不一致的:Left(string, count), Insert(substring, string, position), REMatch(reg_expression, string), REReplace(字符串、正则表达式、子字符串 [, 范围])
      • 嘿,尝试一下 PHP,您很快就会渴望只处理两个变体。 ;)
      • (但是是的,rematch/refind 和 rereplace 之间的不匹配尤其如此bugs me!)
      【解决方案3】:

      作为查询字符串的一部分传递的任何变量都在 URL 范围内可用 - 这是一个“内置”结构。

      下面是一些示例代码,可以将这些变量放入您的示例中:

      <cfoutput>
          #url.id# <br />
          #url.key# <br />
          #url.output#
      </cfoutput>
      

      添加到我的答案以匹配新信息和 mbrusche 的示例:

      <cfset urlString = listRest( urldata, "?" ) />
      <cfoutput>
          <cfloop list="#urlString#" index="URLPiece" delimiter="&">
              Key: #listFirst( urlPiece, "=" )# Value: #listLast( urlPiece, "=" (# <br />
          </cfloop>
      </cfoutput>
      

      【讨论】:

      • 在这种情况下,url 作为字符串存储在数据库中,所以我需要将其解析为变量,而不是 url 范围的一部分。
      • 使用 & 作为分隔符循环字符串。然后你可以从那里分离出这些值。 &lt;cfloop list="#string#" index="urlpiece" delimiter="&amp;"&gt;#urlpiece#&lt;/cfloop&gt;
      • 啊……我现在明白了。 mbrusche 的想法可行,但我想我会先去掉域名和路径: string = listRest(string, "?") 否则循环的第一次迭代将包含协议、域名、路径和文件。在该循环中,您可以执行 listFirst( urlPiece, "=") 来获取键和 listLast( urlPiece, "=") 来获取值。
      • 我将更新我的示例,因为我认为它具有误导性。在我的实际 url 中,键是第一个 url 变量,所以我不能使用 & 作为分隔符。
      • 运行下面的例子我最终得到的值为0,但我认为它应该是整个键值? docs.google.com/spreadsheet/…" /> 键:# listFirst(urlPiece, "=")# 值:#listLast(urlPiece, "=")#
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2011-05-15
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多