【问题标题】:How to extract weight and other meta data from a text block?如何从文本块中提取重量和其他元数据?
【发布时间】:2015-07-18 12:35:33
【问题描述】:

需要处理的示例文本是:

GLENSTAL 超成熟 COL CHEDDAR 200 GMS,原味华夫饼公司。 英式 130G,LIFCO-SHREDDED MOZAREAL-500GM,CAPRICON 美味面包 -BIG,LUSINE 多谷切片面包,有机混合果汁 10X200ML,可乐 330ML(016) PHOENIX ORGANIC,水果果汁 10X 200ML, 有机果汁500ML10X

我必须从本文中提取重量、单位以及包装是否可用,如“10X 或 6X”。我尝试使用正则表达式解决它,但它不适用于所有条件。

我试过的代码是:

$weight_unit = explode(" ", $title_string);
 $units = array("LITRE", "LTRS", "LTR", "LIT", "GMS", "LBS", "KG", "GM", "GR", "ML", "OZ", "LB", "G", "L");
 for ($m = 0; $m < sizeof($weight_unit); $m++) {
   foreach ($units as $unit) {
     if (preg_match('/^[0-9A-Z.]*([0-9][A-Z]|[A-Z][0-9])[0-9A-Z]*$/',
          $weight_unit[$m]) && strpos($weight_unit[$m], $unit) !== FALSE) {
          $product["weight"] = preg_replace("/[A-Za-z]/", '', $weight_unit[$m]);
          $product["unit"] = $unit;
          break;
      }
   }
 }

【问题讨论】:

  • 如果您在给出示例输入的情况下也发布所需的输出,那么您的问题对于未来的读者和希望发布答案的志愿者来说会更有价值。你想用-BIG做什么?您究竟希望如何解析 COLA 330ML(016) PHOENIX ORGANIC?请发布您所需的完整输出数组,因为我想提供一个全面且优化的答案,以便您可以授予绿色勾号,并且可以认为此问题已得到充分解决。

标签: php regex text


【解决方案1】:

你可以试试:

(\d+X\s?)?\d+\s?(LITRE|LTRS|LTR|LIT|GMS|LBS|KG|GM|GR|ML|OZ|LB|G|L)(\d+X\s?)?

如果您只想匹配这些单位。在正则表达式中:

  • (\d+X\s?)? - 可以匹配一个或多个数字与 X(10X 等),
  • \d+\s? - 一个或多个数字和一个或没有空白字符
  • (LITRE|LTRS|LTR|LIT|GMS|LBS|KG|GM|GR|ML|OZ|LB|G|L) - 的替代品 你的单位,
  • (\d+X\s?)? - 可以匹配一个或多个数字,单位后带有 X

DEMO

【讨论】:

    【解决方案2】:

    尝试仅使用一个正则表达式完成所有这些操作可能不值得您费心。也许你可以让它工作,但下一个工作的人将很难,除非她习惯于对调制解调器吹口哨。 :-) 让我们尝试一系列嵌套循环。

    $txt = "GLENSTAL EXTRA MATURE COL CHEDDAR 200 GMS, ORIGINAL WAFFLES CO. ENGLISH 130G, LIFCO-SHREDDED MOZAREAL-500GM, CAPRICON TASTY BREAD -BIG, LUSINE MULTI GRAIN SLICED BREAD, ORGANIC MIXED FRUITS JUICE 10X200ML, COLA 330ML(016) PHOENIX ORGANIC, FRUITS JUICE 10X 200ML, ORGANIC FRUITS JUICE 500ML10X";   
    $units = array("LITRE", "LTRS", "LTR", "LIT", "GMS", "LBS", "KG", "GM", "GR", "ML", "OZ", "LB", "G", "L");
    /* break up your string at the commas, so you handle each item by itself */
    $items = preg_split("/\s*,\s*/", $txt);
    
    /* work through the items one by one */
    foreach ($items as $item) {
        $amtnum = 1;
        $amtunit = "";
        $packnum = "1";
    
        /* break up the item description into tokens, where 
         * each number string and letter string gets its own token.
         * deal with (123) parenthesized number strings as well.
         *   e.g.   "FRUITS JUICE" "10" "X" "200" "ML"
         *   and    "COLA" "330" "ML" "(016)" "PHOENIX ORGANIC"
         */
        $toks = preg_split("/(\(\d+\)|\d+|[^\d\(\)]+)/", $item,-1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
        /* work backward through array of tokens, using array_pop */
        while ($tok = array_pop($toks)) {
            /* is the present token in your array of units? */
            if (in_array(strtoupper($tok), $units)) {
                /* yes. grab next token as the number of units */
                $amtunit = $tok;
                $amtnum = array_pop($toks);
            }
            /* is this an X (for a 16X pack or some such thing ? */
            if ($tok == 'X') {
                /* yes, grab next token as the number of items in the pack */
                $packnum = array_pop($toks);
            }
            /* do what you will with the result */
            echo $amtnum, $amtunit, $packnum;
        }
    }
    

    这一行是解决您的问题的关键。让我们检查一下。

        $toks = preg_split(
                "/(\(\d+\)|\d+|[^\d\(\)]+)/", 
                $item,-1, 
                PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
    

    preg_split 将字符串拆分为数组。 PREG_SPLIT_DELIM_CAPTURE 作为修饰符意味着将正则表达式中的内容包含在结果数组中。 PREG_SPLIT_NO_EMPTY 表示结果数组中不包含空字符串。

    让我们看看正则表达式本身。我将添加空格以使其更易于阅读。

    (  \(\d+\)  |  \d+  |  [^\d\(\)]+  )  
    

    它以括号() 开头和结尾。这适用于PREG_SPLIT_DELIM_CAPTURE

    然后它包含三个替代匹配表达式,以| 分隔。

    第一个是括号,数字和括号。这与您的测试数据集中的字符串 (016) 匹配。

    第二个是一个普通的数字。匹配诸如“300”之类的内容。

    第三个是由字母、空格等组成的字符串,除了数字和括号之外的任何内容。例如,匹配“GMS”和“FRUITS JUICE”。

    这可能是使用正则表达式进行解析工作的一种相当稳健的方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2016-07-24
      相关资源
      最近更新 更多