【问题标题】:Regular expression for matching quantities and unit匹配数量和单位的正则表达式
【发布时间】:2010-08-07 15:10:24
【问题描述】:

我需要从这样的字符串中提取数量和单位

1 tbsp
1tbsp 
300ml
300 ml
10grams
10 g

数量始终是数字,然后可能有也可能没有空格,然后是单位。它们可能是 15 - 20 个不同的单元,可以来自我们定义的列表(可能是数组)

解决方案可以是 javascript 或 PHP,因为我需要先拆分它们,然后再将它们存储到数据库中。即它们需要分开存放。

谢谢

编辑:很抱歉说清楚。每个新行代表一个新字符串。那就是字符串只包含 10g 或 300ml - 所以我们只需要一次拆分一个单位和一个数量。

【问题讨论】:

  • 他们会一直出现在这样的列表中吗?还是有时会出现其他文字?
  • @hookedonwinter - 仅靠他们自己。没有其他文字。

标签: php javascript regex


【解决方案1】:

正则表达式:

/(\d+)\s*(\D+)/

代码:

preg_match_all('/(\d+)\s*(\D+)/', $ingredients, $m);

$quantities = $m[1];
$units = array_map('trim', $m[2]);

$quantities$units 是:

Array
(
    [0] => 1
    [1] => 1
    [2] => 300
    [3] => 300
    [4] => 10
    [5] => 10
)
Array
(
    [0] => tbsp
    [1] => tbsp
    [2] => ml
    [3] => ml
    [4] => grams
    [5] => g
)

见:http://ideone.com/MSH8t

如果您使用它,您不必准备好单位列表。但这假设您的单位上没有数字字符,并且您的数量只是数字。

【讨论】:

    【解决方案2】:

    好的,你可以做的是创建一个允许的单元数组,然后使用array_map 对数组中的每个单元应用preg_quote(这样如果单元中有任何字符是特殊字符一个正则表达式,它们将被转义),然后构造一个正则表达式:

    $units = array("tbsp", "ml", "g", "grams"); // add whatever other units are allowed
    $pattern = '/^(\d+)\s*(' . join("|", array_map("preg_quote", $units)) . ')$/';
    

    $pattern 将因此变成类似于/^(\d+)\s*(tbsp|ml|g|grams)$/,然后您可以使用它来检测字符串中看起来像单位的东西:

    $matches = array();
    // assuming you have an array of measurement strings...
    foreach ($measurement_strings as $measurement)
    {
      preg_match($pattern, $measurement, $matches);
      list(, $quantity, $unit) = $matches;
      // ...
    }
    

    因为该模式定义了两个捕获组,分别用于数量和单位,然后您可以将它们从匹配中提取出来并使用它们做您想做的事情。

    (我已经更新了我的答案,基于每行是一个单独的字符串的问题更新)。

    【讨论】:

    • 我认为 OP 正在寻找更多与此相关的内容,例如如何使用该模式来提取匹配数组。
    • @David 太棒了!我喜欢动态添加单位的能力。我认为正则表达式有错误?您的代码中的模式与您的解释中的模式不同。 $//$。试图让它在我的ide中工作。但到目前为止很棒
    • @hookedonwinter 哎呀,是的,这是一个错字。 ^$ 是行锚的开始和结束,斜杠是 preg_* 函数需要的模式字符的开始和结束。
    【解决方案3】:

    也许一些简单的事情就足够了,就像这样:

    ^([0-9]+)\s*([a-zA-Z]+)\s*$
    

    【讨论】:

    • 那里的那些开始和结束锚点使得匹配多行毫无用处
    • 基本上你是对的,但这也取决于实现。在 c# 中,您可以定义 RegexOptions.Multiline,并且它在多行中工作。例如 new Regex(@"^([0-9]+)\s*([a-zA-Z]+)\s*$", RegexOptions.Multiline) 等价于 new Regex(@"([0 -9]+)\s*([a-zA-Z]+)\s*")
    • @quantum:OP 已经更新了问题,说字符串将被单独处理,而不是作为多行文本块,所以锚应该不是问题。
    • 您是说带有锚点的多行正则表达式与非多行正则表达式没有锚点相同吗?这是不对的。多行^([0-9]+)\s*([a-zA-Z]+)\s*$ 等价于(?<=\A|\n)([0-9]+)\s*([a-zA-Z]+)\s*(?=\n|\Z)
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-06
    • 2011-01-06
    • 2012-01-31
    相关资源
    最近更新 更多