开发者

Regex that replaces a css value in CSS

Hey. I'm trying to parse a CSS file using PHP.

I'm trying to run this expression:

"/(". $selector . "\\s*{[\\w\\s:\\-;()#]*)(" . $property . ":)([^;}]+)(}?)/Ui"

This regex开发者_JAVA技巧 is supposed to pin down a specific property within a selector and allow me to change it's value/remove it.

rational:

  1. match the selector and it's text preceding to the property
  2. match the property name
  3. match the property value
  4. if the value ends by the } sign - catch it as well

The broken bit is #3 - For some unknown reason, when I run this through preg_match, the value group(#3) only catches the first char.

For example, running this expression:

preg_replace("/(h1\s*{[\w\s:\-;()#]*)(font-size:)(([^;}])+)(}?)/Ui","$1 $4",$css);

(find the font-size property of the h1 selector, and remove the property and value)

on this css group:

h1{
    background:#fff;
    font-size:10px;
    text-align:underline;
    color:#abc;
}

I get:

h1{
    background:#fff;
    /* note that although the property was matched and removed,
       the value only matched the 1st char: 1 */ 
    0px; 
    text-align:underline;
    color:#abc;
}

I've tried to check the expression through some test tools and it worked fine, so I'm guessing this is a preg* specific problem.

any ideas what I'm doing wrong?


Parsing CSS only with regexp is masochism.

You can find some information how to parse CSS in this CSS object model specification. Sorry I was able to find only Editor's draft, the other URLs seems to be broken.


(([^;}])+)(}?) does actually match only one char (with modifier U).

You have to use something like this: ([^;}]+)(;|})

Additionally it's not bad to escape curly braces.

The full RegEx:

preg_replace('/('.$selector.'\s*\{[\w\s:\-;\(\)#]*)('.$property.'\s*:)([^;\}]+)(;|\})/Ui', '$1 $4', $css);


dont regroup the 3rd brackets, try:

preg_replace("/(h1\s*{[\w\s:\-;()#]*)(font-size\s*:)([^;}]+)(}?)/Ui","$1 $4",$css);

in addition, i added \s* after the property, to allow it to catch things like

font-size : 10px


Your torturing yourself with the "ungreedy" modifier '/U', I wouldn't use it.
The real problem is that you are making provisions for 'property:value' ending to be either a ';' or a '}'

So, it can be either [;}] that is your final delimeter. There is really no easy way to implement that while preserving the formatting, I redid your regex a little. Think php does Perl compatible regex, so rearranged and doctored up the last part to a reasonable working model. Its not for the faint of heart.

The modifiers are Perl's /xi stands for expanded and case insensitive.
Don't use php's /U modifier on this! There is only 2 capture groups now, 1 & 2.

Regex as unquoted with variables:

/((?:$selector)\s*\{[\w\s:;()#-]*?)\s*(?:$property)\s*:(?:(?!\s*\})[^;])+(?:(?=;);[^\S\n]*)?(\s*\}?)/i;

Regex catted as a string:

'/((?:' . $selector . ')\s*\{[\w\s:;()#-]*?)\s*(?:' . $property. ')\s*:(?:(?!\s*\})[^;])+(?:(?=;);[^\S\n]*)?(\s*\}?)/xi;'

Test case in Perl:

use strict;
use warnings;

my ($selector, $property) = ( 'h1 | h2', 'font-size' );

my $sample = 
'
h1{
    background:#fff;
    font-size:10px;
    text-align:underline;
    color:#abc;
}
h2{
    text-align:strikethrough;
    background:#fefe;
    color:#dbd;
    font-size:10px
} ';

my $rx = qr/
  (                      # group 1
      (?:$selector)
      \s*
      \{
         [\w\s:;()#-]*?
  )
         \s* (?:$property) \s*: (?: (?!\s*\}) [^;] )+
         (?:
             (?=;) ;[^\S\n]*
         )?
  (                      # group 2
      \s*
      \}?
  )
/xi;

print $rx,"\n\n";

$sample =~ s/$rx/$1$2/g;

print $sample,"\n";

Output:

(?ix-sm:
  (                      # group 1
      (?:h1 | h2)
      \s*
      \{
         [\w\s:;()#-]*?
  )
         \s* (?:font-size) \s*: (?: (?!\s*\}) [^;] )+
         (?:
             (?=;) ;[^\S\n]*
         )?
  (                      # group 2
      \s*
       \}?
  )
)

h1{
    background:#fff;
    text-align:underline;
    color:#abc;
}
h2{
    text-align:strikethrough;
    background:#fefe;
    color:#dbd;
}
/((?:h1 | h2)\s*\{[\w\s:;()#-]*?)\s*(?:font-size)\s*:(?:(?!\s*\})[^;])+(?:(?=;);[^\S\n]*)?(\s*\}?)/xi;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜