Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

meaning of (\/?) in regex / is (\w+)([^>]*?) a redundancy?

this regular expression should match an html start tag, I think.

var results = html.match(/<(\/?)(\w+)([^>]*?)>/);

I see it should first capture the <, but then I am confused what this capture (\/?) accomplishes. Am I correct in reasoning that the ([^>]*?)> searches for every character except > >= 0 times? If so, why is the (\w+) capture necessary? Doesn't it fall within the purview of [^>]*?

like image 476
1252748 Avatar asked Jul 03 '13 16:07

1252748


People also ask

What does W * mean in regex?

In regex, the uppercase metacharacter denotes the inverse of the lowercase counterpart, for example, \w for word character and \W for non-word character; \d for digit and \D or non-digit.

What is W in python regex?

\w -- (lowercase w) matches a "word" character: a letter or digit or underbar [a-zA-Z0-9_]. Note that although "word" is the mnemonic for this, it only matches a single word char, not a whole word. \W (upper case W) matches any non-word character.

What does * do in regex?

The Match-zero-or-more Operator ( * ) This operator repeats the smallest possible preceding regular expression as many times as necessary (including zero) to match the pattern. `*' represents this operator. For example, `o*' matches any string made up of zero or more `o' s.

What is the use of class W in regex?

Definition and Usage The \w metacharacter matches word characters. A word character is a character a-z, A-Z, 0-9, including _ (underscore).


2 Answers

Take it token by token:

  • / begin regex literal
  • < match a literal <
  • (\/?) match 0 or 1 (?) literal /, which is escaped by the \
  • (\w+) match one or more "word characters"
  • ([^>]*?) lazily* match zero or more (*?) of anything that is not a >
  • > match a literal >
  • / end regex literal

lazily* - adding "?" after a repetition quantifier will make it perform lazily, meaning the regex will match the preceding token the minimum number of times. See the documentation.

So essentially this regular expression will match "<", potentially followed by a "/", followed by any number of letters, digits, or underscores, followed by anything that is not a ">", and finally followed by a ">".

That being said, the token (\w+) is not redundant, as it ensures there is at least one word character in between < and >.

Please be aware that attempting to parse HTML with regular expressions is generally a bad idea.

like image 144
jbabey Avatar answered Oct 19 '22 23:10

jbabey


Using the power of debuggex to generate you an image :)

<(\/?)(\w+)([^>]*?)>

Will be evaluated like this

Regular expression image

Edit live on Debuggex

As you can see, it matches HTML-tags (opening and closing tags). The regex contains three capture groups, capturing the following:

  1. (\/?) existence of / (it's a closing tag, if present)
  2. (\w+) name of the tag
  3. ([^>]*?) everything else until the tag closes (e.g. attributes)

This way it matches <a href="#">. Interestingly it does not match <a data-fun="fun>nofun"> correctly because it stops at the > within the data-fun attribute. Although (I think) > is valid in an attribute value.

Another funny thing is, that the tag-name capture, does not capture all theoretically valid XHTML tags. XHTML allows Letter | Digit | '.' | '-' | '_' | ':' | .. (source: XHTML spec). (\w+), however, does not match ., -, and :. An imaginary <.foobar> tag will not be matched by this regex. This should not have any real life impact, though.

You see that parsing HTML using RgExes is a risky thing. You might be better of with a HTML parser.

like image 44
tessi Avatar answered Oct 20 '22 00:10

tessi