【问题标题】:Complex string parsing in JavascriptJavascript中的复杂字符串解析
【发布时间】:2014-02-21 00:40:07
【问题描述】:

我正在尝试在 JavaScript 中解析一个复杂的字符串,但我对正则表达式非常糟糕,所以我运气不佳。数据被加载到一个格式如下的变量中:

Miami 2.5 O (207.5) 125.0 | Oklahoma City -2.5 U (207.5) -145.0 (Feb 20, 2014 08:05 PM)

我正在尝试按照以下参数解析该字符串:

1) 每个值都必须加载到自己的变量中(IE:Miami 的单独变量,2.5 O,(207.5) 等)
2) 字符串必须在管道字符处拆分(我使用 .split(" | ") 进行此操作)
3) 我正在处理包含空格的城市名称
4)末尾的日期一定要隔离删除

我感觉必须使用正则表达式,但我非常希望有一种不同的方法来解决这个问题。提供的示例就是这样,来自更大数据集的示例。如果需要,我可以提供完整的数据集。

我的问题更直接的版本:鉴于上面的数据,我可以使用哪些概念/程序来智能地将字符串元素解析为自己的变量?

如果必须使用 RegEx,我需要多个表达式吗?

提前感谢您的帮助!

编辑:为了为解决方案提供多种途径,我还将解释总体问题。此数据是一个 RSS/XML 项的返回。上面提到的字符串是体育赔率,都包含在我正在使用的提要的标题节点中。如果有人有更好的用于体育赔率的 XML / RSS 提要,我也会为此欣喜若狂。

编辑 2:感谢回复,我可以运行与所需数据点匹配的 RegEx。我现在无法遍历匹配项并正确返回它们。我已将 RegEx 加载到它自己的函数中:

function regExExtract (txt){
    var exp = /([^|\d]+) ([-\d.]+ [A-Z]) (\([^)]+\)) ([-\d.]+) (\([^)]+\))?/g;
    var comp_arr = exp.exec(txt);

    return comp_arr;        
}

它的调用方式是:

var title_arr = regExExtract(title);  

标题加载了上面列出的数据字符串。我假设我正确使用了全局标志以确保考虑所有匹配项,但我不确定我是否正确加载了匹配项。我为我的无知道歉,这对我来说是全新的。

按照下面的要求,我的预期输出最终是一个表格,每个城市都有一行,以及它的后续数据。每行中的每个单元格对应一个数据点。

我已经用我所做的创建了一个 JS Fiddle,预期的输出是什么: http://jsfiddle.net/vDkQD/2/

可能的最终编辑:在 Robin 和 rewt 的帮助下,我想出了:
http://jsfiddle.net/hMJx3/

【问题讨论】:

  • 您无法更改我想的字符串的格式?这对于自动解析来说太可怕了(但并非不可能)。
  • 正确,我无法更改字符串的格式。它是从一个 XML Feed 文件中返回的,在该文件中,所有数据都放入了 title 节点。这是一场可怕的噩梦。
  • 你能准确地显示你想要的输出吗?

标签: javascript jquery regex string parsing


【解决方案1】:

不会像

这样的正则表达式
/([^|\d]+) ([-\d.]+ [A-Z]) (\([^)]+\)) ([-\d.]+) (\([^)]+\))?/g

成功了吗?显然,这是基于您提供的示例字符串,如果有其他可能的模式,则应该更新......但如果它是 that 固定的,它并不那么复杂。

之后,您只需检查每场比赛的捕获组,然后您的数据就会被解析。现场演示好玩:http://regex101.com/r/kF5zD3

说明

  • [^|\d] 除了管道或数字之外的任何东西。这是为了解释 [a-zA-Z ] 可能无法捕捉到的奇怪城市名称
  • [-\d.] 一个数字、一个点或一个连字符
  • \([^)]+\) 左括号,所有不是右括号的,右括号。

关于正则表达式的快速不完整指针

  • 这里,正则表达式是/ 之间的部分。 g after 是一个标志,因此正则表达式在第一场比赛后不会停止,并且会返回每场比赛
  • 匹配是整个表达式将找到的。在这里,匹配将是字符串中两个| 之间的所有内容。捕获组是一个非常有用的工具,它允许你从这个匹配中提取数据:它们由括号分隔,括号是正则表达式中的一个特殊字符。 (a)b 将匹配 ab,此匹配的第一个捕获组将是 a
  • [...] 表示里面的每个字符都可以。 [abc] 将匹配 abc
  • + 是一个量词,另一个特殊字符,意思是“我之前的一个或多个”。 a+ 表示“一个或多个 a 并将匹配 aaaaa
  • \d[0-9] 的快捷方式(是的,-[...] 内部的特殊范围字符。这就是为什么在[-\d.] 中,它相当于[-0-9.],它是直接跟在左括号之后)
  • 由于括号是特殊字符,当你真正想匹配一个括号时你需要转义:正则表达式(\(a\))b将匹配(a)b,这个匹配的第一个捕获组将是(a)和括号
  • ? 表示前面的内容是可选的(零个或一个实例)
  • ^ 放在 [...] 语句的开头时,表示“除了括号中的内容之外的所有内容”。 [^a]+ 将匹配 bcd-*ù 但不匹配 aa

如果您真的对正则表达式一无所知,因为我相信它们是适合您情况的工具,我建议您快速浏览一下教程,以便更好地了解您正在处理的内容。设置标志、循环匹配及其各自捕获的组的方式将取决于您的语言以及您如何调用正则表达式。

【讨论】:

  • 天哪,这可能会做到。现在我只需要学习如何实现它进行测试。一旦我这样做了,就会更新评论。
  • 如果您对正则表达式一无所知(而且我认为它们是适合您情况的工具),您可能想快速浏览一下即使是简短的教程,这样您就不会 完全在雾中。我会更新一些指针
  • 非常感谢。我已通读教程,但无法处理多个匹配项。现在,表达式的工作正常,但我只能返回第一个实例参数(管道之前的数据)。我不确定如何在管道之后访问数据。
  • @Vaune:这可能是因为您没有设法正确设置g(全局)标志:正则表达式将在第一次匹配时停止,因此不会在管道之后进行匹配。如果您遇到困难,请展示您的一些代码,人们会提供帮助。我更新了一些随机信息以帮助您入门,但几个小时内不会回来。玩得开心!
【解决方案2】:
[A-z][a-z]+( [A-z][a-z]+)* -?[0-9]+\.[0-9] [OU] \(-?[0-9]+\.[0-9]\) -?[0-9]+\.[0-9]

在以下假设下,这应该匹配您的长字符串的单个部分:

  • 城市仅由字母字符组成,每个单词都以大写字符开头,并且长度至少为 2 个字符。
  • 数字有一个可选的符号,小数点后只有一位数
  • 单个字符是 O 或 U

现在由您决定:

  • 正确创建捕获括号
  • 检查我的假设是否正确

为了匹配日期:

\([JFMASOND][a-z]{2} [0-9]?[0-9], [0-9]{4} [0-9]{2}:[0-9]{2} [AP]M\)$

【讨论】:

  • 这很好,但是它并没有隔离价值组件。但是,它确实可以更轻松地定位单个短语。它省略了日期,并匹配管道前后的两个核心组件。现在我只需要找到一种方法来进一步拆分每个组件的核心价值。
  • @Vaune 正如我所写的,这取决于你。您基本上需要将括号放在我的正则表达式中的正确位置,为了便于阅读,我省略了它们。
  • 明白,谢谢。我对 RegEx 的经验为 0,所以我最初并不了解。我希望我能投票给你:)
  • @Vaune 尽可能简单地接受最有帮助的答案,这也将为您赢得 2 声望。
猜你喜欢
  • 2013-01-06
  • 1970-01-01
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多