如何从文本块中提取权重和其他元数据?

时间:2015-07-18 12:35:33

标签: php regex text

需要处理的示例文本是:

  

GLENSTAL EXTRA MATURE COL CHEDDAR 200 GMS,ORIGINAL WAFFLES CO。   英文130G,LIFCO-SHREDDED MOZAREAL-500GM,CAPRICON TASTY面包   -BIG,LUSINE多粒面包片,有机混合果汁JUICE 10X200ML,COLA 330ML(016)PHOENIX有机,水果汁10X 200ML,   有机果汁JUICE 500ML10X

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

我尝试过的代码是:

{{1}}

2 个答案:

答案 0 :(得分:3)

您可以尝试:

(\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

答案 1 :(得分: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”。

这可能是使用正则表达式执行此解析作业的一种相当强大的方法。