Search code examples
phpcssregexreplacetext-parsing

Regex to insert words into background declaration of a CSS file


I want to parse a CSS file and every time there is background:[some properties] (12px) (10px) [some properties]; changes to `background:[some properties] right (12px) top (10px) [some properties];

I have tried this regex:

(background\s*:.*?)\s(\d+([a-z]+|%|))\s+(\d+([a-z]+|%|));

but it catches: background:url(../images/header.jpg) top no-repeat; height:123px; float:left; padding:65px left 0px top 0px 120px;

You can see in this fiddle, the only string it should catch is this: background:url(../images/header.jpg) 10px 0 no-repeat; but it catches an extra string.

How do I stop the regex pattern after ;, so it will not continue to the next css rule? and what is the right pattern here?


Solution

  • You can try this:

    $result = preg_replace('/\bbackground\s*:[^;]*?\K(\d+(?:px|e[mx]|%)?+\s+)(\d+(?:px|e[mx]|%)?+)/i', 'right $1 top $2', $string);
    

    example:

    <?php
    
    $string = <<<'LOD'
    #banner{width:814px; background:url(../images/header.jpg) top no-repeat; height:123px; float:left; padding:65px 0px 0px  120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
    
    #banner2{width:814px; background:url(../images/header.jpg) 10px  0 no-repeat; height:123px; float:left; padding:65px 0px 0px  120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
    
    #banner3{width:814px; background:url(../images/header.jpg) left 10px  top 0 no-repeat; height:123px; float:left; padding:65px 0px 0px  120px; font-family: Georgia, "Times New Roman", Times, serif; font-size:30px; color:#fff;}
    LOD;
    
    $result = preg_replace('/\bbackground\s*:[^;]*?\K(\d+(?:px|e[mx]|%)?+)\s+(\d+(?:px|e[mx]|%)?+)/i', 'right $1 top $2', $string);
    
    print_r($result);
    

    pattern details:

    (?:....) is a non capturing group

    \K resets all the match from match result before it

    \b is a word boundary. It's a zero-width assertion, a border between a member of the \w character class and another character

    [^;] is a negative character class that means "all character except ;"

    a quantifier is by default greedy (it catch all that is possible), if you want it catch the less possible (lazy), you must add a question mark after (*?, +?, ??, {1,5}?)