There seems to be a minor issue with the forward slash placement between weight and sizes. To resolve this, consider combining into one regex pattern where everything except anchors is optional. This will help align things properly to avoid 'normal' appearing on most variables.
Edit I came across a reference that details how CSS Font Shorthand Property parsing works: http://www.w3schools.com/cssref/pr_font_font.asp
edit2 The hard spaces delimiters have been adjusted to come after the optional parts and between the required parts.
# /(?:(?:(normal|italic|oblique|initial|inherit)\s+)?(?:(normal|small-caps|initial|inherit)\s+)?(?:((?:normal|bold|bolder|lighter|initial|inherit|\d+))\s+)?(?:(smaller|small|x-small|xx-small|medium|larger|large|x-large|xx-large|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))(?:\/(normal|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px)))?\s+)(?:(initial|inherit|(?:"[^"]*"|'[^']*'|[a-zA-Z-]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[a-zA-Z-]+))*))|(caption|icon|menu|message-box|small-caption|status-bar|initial|inherit))/
#### CSS - Font Shorthand Property
#### Reference: http://www.w3schools.com/cssref/pr_font_font.asp
#### --------------------------------
#### font:
(?:
#### User Defined Fonts
#### ------------------
##### Style (optional)
(?:
( # (1 start), Style
normal
| italic
| oblique
| initial
| inherit
) # (1 end)
\s+ # delimiter
)?
##### Variant (optional)
(?:
( # (2 start), Variant
normal
| small-caps
| initial
| inherit
) # (2 end)
\s+ # delimiter
)?
##### Weight (optional)
(?:
( # (3 start), Weight
(?:
normal
| bold
| bolder
| lighter
| initial
| inherit
| \d+
)
) # (3 end)
\s+ # delimiter
)?
##### Size (required)
(?:
( # (4 start), Size
smaller
| small
| x-small
| xx-small
| medium
| larger
| large
| x-large
| xx-large
| initial
| inherit
| \d+
(?: \% | in | cm | mm | em | rem | ex | pt | pc | px )
) # (4 end)
##### Line Height (optional)
(?:
/ # Separator
( # (5 start), Line height
normal
| initial
| inherit
| \d+
(?: \% | in | cm | mm | em | rem | ex | pt | pc | px )
) # (5 end)
)?
\s+ # delimiter
)
##### Family (required)
(?:
( # (6 start), Family
initial
| inherit
| (?: " [^"]* " | ' [^']* ' | [a-zA-Z-]+ )
(?:
\s* , \s*
(?: " [^"]* " | ' [^']* ' | [a-zA-Z-]+ )
)*
) # (6 end)
)
|
#### OR,
#### Use the Fonts used by these OS elements
#### ------------------
#### Values (required, if used)
( # (7 start), Use values
caption
| icon
| menu
| message-box
| small-caption
| status-bar
| initial
| inherit
) # (7 end)
)
Perl Test case
$str = 'font:normal small-caps 120%/120% "Times New Roman", sans-serif;';
if ( $str =~ /(?:(?:(normal|italic|oblique|initial|inherit)\s+)?(?:(normal|small-caps|initial|inherit)\s+)?(?:((?:normal|bold|bolder|lighter|initial|inherit|\d+))\s+)?(?:(smaller|small|x-small|xx-small|medium|larger|large|x-large|xx-large|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px))(?:\/(normal|initial|inherit|\d+(?:\%|in|cm|mm|em|rem|ex|pt|pc|px)))?\s+)(?:(initial|inherit|(?:"[^"]*"|'[^']*'|[a-zA-Z-]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[a-zA-Z-]+))*))|(caption|icon|menu|message-box|small-caption|status-bar|initial|inherit))/)
{
print "\nmatched '$&'\n\n";
print "style = '$1'\n";
print "variant = '$2'\n";
print "weight = '$3'\n";
print "size = '$4'\n";
print "height = '$5'\n";
print "family = '$6'\n";
print "values = '$7'\n";
}
Output >>
matched 'normal small-caps 120%/120% "Times New Roman", sans-serif'
style = 'normal'
variant = 'small-caps'
weight = ''
size = '120%'
height = '120%'
family = '"Times New Roman", sans-serif'
values = ''