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 />';

I really don't know what meaning in preg_match. For example "?P<title>" , "\d+g"

Constantin Groß
  • 9,010
  • 4
  • 17
  • 44
red23jordan
  • 2,663
  • 10
  • 34
  • 53

3 Answers3

2

from the manual of preg_match():

Named subpatterns now accept the syntax (?) and (?'name') as well as (?P). Previous versions accepted only (?P).

so, (?P<grammars>.*) will make you have a value in $m['grammars']

\d+ matches 1 or more digits, g matches the letter g

.* greedy match on any character, 0 or more times - in your case, this match will be put in the title or grammars match variable.

I recommend you read on some basic regex tutorials - the .* construct is a really basic one

Tudor Constantin
  • 24,065
  • 7
  • 44
  • 66
  • 1
    This tutorial is great for learning named subpatterns (and everything else in that query) http://net.tutsplus.com/tutorials/php/advanced-regular-expression-tips-and-techniques/ – DallinDyer Oct 07 '11 at 06:53
  • @DallinDyer It is an advanced tutorial, is there any basic tutorial?? – red23jordan Oct 07 '11 at 07:00
  • @Tudor I still don't know "(?P.*)" , what is the meaning of ".*"?? – red23jordan Oct 07 '11 at 07:02
  • Here is a quick cheat sheet that may help you out. http://www.autohotkey.com/docs/misc/RegEx-QuickRef.htm. .* = zero or more of any character – DallinDyer Oct 07 '11 at 07:14
2

The meaning is this :

# (?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 «\)»

This it the output of regexbuddy. You should use a regex helper. Helps a lot :)

FailedDev
  • 25,171
  • 9
  • 48
  • 70
1

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

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

In english it would be something like this:

look for one or more characters -- call this 'title' (Instant Oats Drink - Chocolate Flavour)

-- followed by --

a space

-- followed by --

one or more numbers ending with a 'g' -- call this 'grammars' (165g)

-- followed by --

a space

-- followed by --

a parenthesis '('

-- followed by --

one or more digits (\d+) ending with a g -- call the \d+g 'portion' (33g)

-- followed by --

a space followed by an x followed by a space. ( x )

-- followed by --

one or more digits -- call this 'times' (the 5)

DallinDyer
  • 1,318
  • 13
  • 14
  • If I want to include space in 'title', what should i do? – red23jordan Oct 07 '11 at 07:33
  • Do want the title broken up more, or do you want a space in the name you are giving your subpattern? – DallinDyer Oct 07 '11 at 07:35
  • Both ^^ 1) I want to broken the title word by word, however, it is one of example, i don't know how many word in title – red23jordan Oct 07 '11 at 08:36
  • 2) i tried (?P.* )(?P<grammars>\d+g) instead of (?P<title>.*) (?P<grammars>\d+g), it is not work.</grammars> – red23jordan Oct 07 '11 at 08:41
  • 1
    If you do not know how many words there are in the title, just grab all of it, and run `split` on the result. There is no (sane) way to get each token in the title in a separate group, except perhaps by putting a fixed number of optional non-space groups and hoping you never get a title with more words than you have groups for. – tripleee Oct 07 '11 at 10:34