有什么办法可以改善这个正则表达式

时间:2010-08-23 01:12:23

标签: javascript regex

我是正规表达方式的新手,所以会对这一点的同行反馈表示赞赏。它将在我的网站上大量使用,因此任何奇怪的边缘情况都可能完全造成严重破坏。我们的想法是在整个单位或分数中输入配方中一定量的成分。由于我的自动完成机制,只有一个数字也是有效的(因为它会弹出一个下拉列表)。这些行有效:

1
1/2
1 1/2
4 cups
4 1/2 cups
10 3/4 cups sliced

该行的数字部分应该是它自己的组,所以我可以用我的分数解析器解析它。数字部分之后的所有内容都应该是第二组。起初,我试过这个:

^\s*(\d+|\d+\/\d+|\d+\s*\d+\/\d+)\s*(.*)$

这几乎可行,但“1 1/2杯”将被解析为(1)(1/2杯)而不是(1 1/2)和(杯)。在稍微摸了一下之后,我确定这是因为我的“OR”条款的排序。 (1)满足\ d +和(。*)满足其余部分。所以我改为:

^\s*(\d+\/\d+|\d+\s*\d+\/\d+|\d+)\s*([a-z].*)$

这几乎可行,但允许诸如“1 1/2/4杯”或“1/2 3杯”之类的怪异。所以我决定强制将一个字母作为有效数字表达式之后的第一个字符:

^\s*(\d+\/\d+|\d+\s*\d+\/\d+|\d+)\s*($|[a-z].*)$

注意我在不区分大小写的模式下运行它。这是我的问题:

  1. 表达能改善吗?我有点不喜欢数字,分数,化合物分数的“OR”列表,但我想不出允许整数,分数或复合分数的方法。

  2. 如果我可以在数字组件之后为每个单词返回一个组,那将是特别好的。例如(10 3/4)组,(杯子)组和(切片)组。之后可以有任意数量的单词。这可能吗?

  3. 谢谢!

2 个答案:

答案 0 :(得分:3)

嗯,在我看来,你根本不需要OR条件(但见下文)。

对于数字位,你可以逃脱:

\d+(\s+\d+/\d+)

将处理所有这些小数值。

我仍然会将你的小数与OR子句分开,因为它可能使事情复杂化。所以我认为你可能会得到类似的东西:

^\s*((\d+\s)?(\d+/\d+)?|\d+(\.\d+)?)\s*([a-z].*)?$
 |   |                  |           |  |
 |   |                  |           |  +--- start of alpha section.
 |   |                  |           +------ optional white space.
 |   |                  +------------------ decimal (nn[.nn])
 |   +------------------------------------- fractional ([nn ][nn/nn])
 +----------------------------------------- optional starting space.

虽然这允许空的小数量,所以你可能会更好地得到你所拥有的东西(单独的OR子句中的整数,小数和小数)。

我更喜欢([a-z].*)?$构造到($|[a-z].*)$我自己,但这可能只是对我的过去厌恶在我的RE中有多个行结束标记: - )


但是,老实说,我认为你可能会试图在这里用热核弹头拍打苍蝇。

确实需要限制输入的内容。我见过要求a pinch of salta handful of sultanas的食谱。我个人认为你可能会限制你允许的内容。我会有一个自由形式的数量字段和一个下拉食品类型(实际上我可能只允许自由形式的批次除非我提供根据冰箱里的东西搜索食谱的能力)。

答案 1 :(得分:1)

我相信这个正则表达式应该做你想要的:

/^\s*(\d+ \d+\/\d+|\d+\/\d+|\d+)\s*(.*)/

为了匹配特定单词,您应该在解析后对空格进行拆分。有一些你不想用正则表达式做的事情;)