Roberto C.
Roberto C.

Reputation: 66

PHP RegEx: match a list in an unknown order

I am trying to match some CSS properties. However, I cannot predict the order they will be in.

Example:

header p {
color:#f2f3ed;
background-color:#353535;
background-image: url(../images/dots.png);
}

However, I should also expect:

header p {
background-image: url(../images/dots.png);
background-color:#353535;
color:#f2f3ed;
}

And any other combination of these three properties. The web application we are building only gives me access to the preg_match function.

Anyone know a way to match every possible combination of properties? I know exactly what the properties will be, I just do not know which order they will come in.

Saying that, I am trying to find a quicker solution than typing out every possible combination and separating it with |

Upvotes: 2

Views: 894

Answers (2)

Raúl Moreno
Raúl Moreno

Reputation: 308

Regex for existence of some words whose order doesn't matter

This works, thanks to the lookahead operator (?= ).

/^(?=.*(?:color|background-color|background-image)\:.*?;).*/gm

or with comments

^            # beggining of line
(?=          # positive lookahead (true if pattern present after current position; in this case the beginning of current line)
  .*         # anything before the pattern we search for
  (?:color|background-color|background-image)\:      # match any of those 3 sequences followed by : char
  .*?;       # anything followed by ; but not looking beyond the first ; found
  )
.*           # match the rest of the chars from where the (?= ) was found.
/gmx         # MODIFIERS: global, multi-line, extended (for comments, ignores spaces and anything after #)

You can try it here:

https://regex101.com/r/tX0hK3/1

The ^ before (?=.* is very important for efficiency! Otherwise the engine would try the search once for each position.

The ending .* (or .+ or .++, possessive) is just for matching the line now we have find the right content.

Upvotes: 1

mario
mario

Reputation: 145492

The super-inexact but also stupidly-easy approach would be use a list of alternatives:

/  ( \s* color:#\w+; | \s* bbb:... | \s* ccc:... ){3}  /x

The quantifier {3} will ensure that three of the alternatives are present, and the order won't matter.

It would however allow three color: properties to match. You'll have to decide if that's important enough, or if it's unlikely enough that anyone will write three consecutive color: statements in your CSS declarations.

Upvotes: 1

Related Questions