这个正则表达式(PHP)的含义是什么?

3
$str = "Instant Oats Drink - Chocolate Flavour 165g (33g x 5)";

preg_match('/(?P<title>.*) (?P<grammars>\d+g) \((?P<portion>\d+g) x (?P<times>\d+)\)/', $str, $m);

echo "Title : " . $m['title'] . '<br />';
echo "Grammars : " . $m['grammars'] . '<br />';
echo "Portion : " . $m['portion'] . '<br />';
echo "Times : " . $m['times'] . '<br />';

我真的不知道preg_match中的含义。例如,"?P<title>""\d+g"

3个回答

2
这句话的意思是:
# (?P<title>.*) (?P<grammars>\d+g) \((?P<portion>\d+g) x (?P<times>\d+)\)

# 
# Match the regular expression below and capture its match into
#  backreference with name “title” «(?P<title>.*)»

#    Match any single character that is not a line break character «.*»
#       Between zero and unlimited times, as many times as possible, giving back as needed (greedy) «*»
# Match the character “ ” literally « »
# Match the regular expression below and capture its match into backreference with name “grammars” «(?P<grammars>\d+g)»
#    Match a single digit 0..9 «\d+»
#       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
#    Match the character “g” literally «g»
# Match the character “ ” literally « »
# Match the character “(” literally «\(»
# Match the regular expression below and capture its match into backreference with name “portion” «(?P<portion>\d+g)»
#    Match a single digit 0..9 «\d+»
#       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»

#    Match the character “g” literally «g»
# Match the characters “ x ” literally « x »
# Match the regular expression below and capture its match into backreference with name “times” «(?P<times>\d+)»
#    Match a single digit 0..9 «\d+»
#       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
# Match the character “)” literally «\)»

这是regexbuddy的输出结果。你应该使用一个正则表达式助手,这会非常有帮助 :)

2

来自preg_match()手册:

命名子模式现在接受语法(?)和(?'name')以及(?P)。之前的版本只接受(?P)。

因此,(?P<grammars>.*)将使您在$m['grammars']中有一个值。

\d+匹配1个或多个数字,g匹配字母g。

.*贪婪地匹配任何字符,0次或多次——在您的情况下,此匹配将放入titlegrammars匹配变量中。

我建议您阅读一些基本的正则表达式教程——.*结构是非常基础的。


1
这篇教程非常适合学习命名子模式(以及查询中的其他内容)http://net.tutsplus.com/tutorials/php/advanced-regular-expression-tips-and-techniques/ - DallinDyer
@DallinDyer 这是一篇高级教程,有没有基础教程? - red23jordan
@Tudor,我仍然不知道"(?P<grammars>.)"," . "的含义是什么? - red23jordan
这是一个可能会对你有所帮助的快速备忘单。http://www.autohotkey.com/docs/misc/RegEx-QuickRef.htm。 .* = 零个或多个任意字符。 - DallinDyer

1

$str = "速溶燕麦饮品 - 巧克力口味 165克(33克x5袋)";

/(?P<title>.*) (?P<grammars>\d+g) \((?P<portion>\d+g) x (?P<times>\d+)\)/

中文可译为:

查找一个或多个字符 - 称之为 'title' (速溶燕麦饮品 - 巧克力口味)

-- 接着 --

一个空格

-- 再接着 --

一个或多个以字母 'g' 结尾的数字 - 称之为 'grammars' (165克)

-- 接着 --

一个空格

-- 再接着 --

左括号 '('

-- 接着 --

一个或多个数字 (\d+),以字母 'g' 结尾 - 称 \d+g 为 'portion' (33克)

-- 接着 --

一个空格后跟一个 x 后再跟一个空格。( x )

-- 再接着 --

一个或多个数字 - 称之为 'times' (这里是 5)


如果我想在“标题”中包含空格,我该怎么做? - red23jordan
你想把标题分得更细一些,还是在给子模式命名时需要加入空格? - DallinDyer
  1. 我想逐字分解标题,但这只是一个例子,我不知道标题有多少个单词。
- red23jordan
我尝试使用(?P<title>.) (?P<grammars>\d+g)而不是(?P<title>.) (?P<grammars>\d+g),但它没有起作用。 - red23jordan
1
如果你不知道标题中有多少个单词,就抓取全部内容,并在结果上运行split。除非通过放置固定数量的可选非空格组并希望你从未获得超过组数的标题,否则没有(明智的)方法将标题中的每个标记分为单独的组。 - tripleee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接