2

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 |

animuson
  • 53,861
  • 28
  • 137
  • 147
Roberto C.
  • 66
  • 3
  • 2
    You should use a CSS parser instead of regular expressions only here. – hakre Nov 18 '11 at 03:17
  • You could also technically call `preg_match` multiple times, once for each property you wish to match, but a parser is the best way to go if this is code that needs to be maintained or used by others. – jswolf19 Nov 18 '11 at 03:57
  • I attempted to build a regex for this but it fried my noodle with having the selector at the front with many matches in the middle. – Scuzzy Nov 18 '11 at 04:30
  • You could also use preg_match_all if that's available and use it to iterate all the lines. – Antti Huima Nov 18 '11 at 06:12

2 Answers2

1

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.

Community
  • 1
  • 1
Raúl Moreno
  • 311
  • 3
  • 14
1

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.

mario
  • 144,265
  • 20
  • 237
  • 291