【问题标题】:ColdFusion extract values from text fileColdFusion 从文本文件中提取值
【发布时间】:2014-06-30 01:10:26
【问题描述】:

技术细节

我想从包含参数名称和值的文本文件中提取值。对于以“request.config”开头的每一行。 (有空行、带有 cmets 的行等,我不想从中提取任何东西)我想提取这些值(粗体):

request.config.my_param_1 = "一些随机字符串";

我认为最好的方法可能是使用 REGEX,但我该怎么做呢?

我认为会有类似于正则表达式的东西,它会提取两个值 request.config.${1} = ${2}; 并检索每行的 ${1} 和 ${2},但前提是它匹配。

我尝试过尝试,但没有成功:

<cfset str = "request.config.MY_PARAM_NAME = 'The parameter VALUE!!';">
<cfset arrSearch = rematch("^request.config.(.*?) = (.*?);$", str) >
<cfdump var="#arrSearch#" label="Extracted values">

不幸的是,这段代码给了我我已经拥有的完整字符串,我只想要两个提取的值

一些 META:我想要做什么

我正在构建一个 Web 应用程序,它允许最终用户修改一些存储在 params_file.cfm 中的应用程序参数。我们希望能够在应用程序中完成,而不是让开发人员手动更改文件中的变量。

我的应用程序首先对后端进行 AJAX 调用,它读取 params 文件,获取所有数据对(param_name、param_value 以及可能稍后在 param_description 上)并将它们作为 JSON 返回以填充我的列表自动完成工具按名称搜索它们(好奇的 Typeahead.js)。当我选择一个参数名称时,该值与一些用于修改它们的控件一起出现(这些控件取决于数据类型,JQuery 用于确定类型)。

问题是 param_value 可以有多种形式。因为这个 params 文件由不同的人维护,它可以有不同的语法。例如,布尔值可以存储为“真”、“真”、真、真(你明白了)。

由于 SerializeJSON 处理类型(布尔值、数字、字符串),我认为我的 REGEX 应该返回不带引号的文本(单引号或双引号),但我在制作该表达式时遇到了麻烦。

我明白了

&lt;cfset match = REFind("^request\.config\.(\S+) = ['|""]?(.*)['|""]?;$", str, 1, "Yes")&gt;

我用request.config.my_param_1 = 'MYTEST123'; 对其进行了测试,它只删除了第一个单引号,由于某种原因,当我不想要任何周围的引号时,表达式返回我MYTEST123'。我的正则表达式需要帮助

【问题讨论】:

  • 为什么你解析文件而不是仅仅包含它?
  • 如果你真的有正当的理由用正则表达式来解析它,你需要更具体的格式 - 即预期/可接受的内容,特别是关于换行符/分号,转义引号,文字结构,等
  • 所以你的文件有一个 CF 结构......为什么不只包含文件,循环你的结构提取键:值对并根据需要将它们放入自己的变量中(虽然我有和@PeterBoughton一起去问为什么)?
  • “我必须将其作为文本文件读取” - 是的,我明白了。我在问为什么。 What are you trying to do?
  • "我的应用程序首先对后端进行 AJAX 调用,它读取 params 文件,获取所有数据对(param_name、param_value 以及可能稍后的 param_description)并将它们作为 JSON 返回" - 将数据存储为 JSON。然后您可以deserializeJson() 进行解析并使用StructKeyArray 等函数以编程方式获取已定义的键等。

标签: regex coldfusion extract text-parsing text-extraction


【解决方案1】:

你不想要REMatch,你想要REFind (docs):

REFind(reg_expression, string [, start, returnsubexpressions ] )

returnsubexpressions 是你需要的,所以...

<cfset str = "request.config.MY_PARAM_NAME = 'The parameter VALUE!!';">
<cfset match = REFind("^request\.config\.(\S+) = (.*);", str, 1, "Yes")>

<cfdump var="#match#">

match 将是一个带有两个键(POSLEN)的结构,列出每个子匹配的位置和长度。

然后您可以将此信息提供给Mid() 并删除实际的子字符串。

不要忘记检查REFind 是否成功,ArrayLen(match.POS) 在您的情况下必须为 3(1 个整体匹配,两个匹配组,想想$0 ..$2)。

要查找整个文件中的所有匹配项,要么

  • 循环运行此函数,将start 设置为match.POS[1] + match.LEN[1] 以进行下一次迭代
  • 或通过&lt;cfloop list&gt; 以换行符Chr(10) 作为分隔符或通过&lt;cfloop array&gt;ArrayToList(file, Chr(10)) 逐行遍历文件。

【讨论】:

  • 我更新了问题描述,我需要帮助调整正则表达式,以便它返回不带单引号或双引号的值字符串(对于布尔值和数字,有时没有引号,有时有)。我调整的 REGEX 返回没有第一个引号的值,但最后一个引号仍然存在。
  • 回答了原始问题后,我将链接与此问题相关的新问题(我仍在为引用而苦苦挣扎)。 stackoverflow.com/questions/23617989/…
  • @dominicbri7 顺便说一句,您可以使用 txt2re (txt2re.com) 通过示例构建正则表达式。也许这对您将来有帮助。
【解决方案2】:

您会想尝试 refind(),而不是 rematch(),因为它返回的数组数据可用于获取和找到子表达式

arrsearch = rematch("^request.config.(.*?) = (.*?);$", line)

只返回整行: #Mid(line,arrsearch.pos[0],arrsearch.len[0])#

返回第一个子表达式(变量名): #Mid(line,arrsearch.pos[1],arrsearch.len[1])#

返回第二个子表达式(值): #Mid(line,arrsearch.pos[2],arrsearch.len[2])#

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
  • 2020-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多