Search code examples
phpregexpreg-replacepreg-replace-callback

How do I swap strings using PHP preg_replace?


I have CSS code and I want to swap left with right and right with left.

Here is example CSS:

.test{text-align:left;margin-left:10px;float:right}
.test_right{text-align:left;border-right:0px;border-left:1px}
.test_left{float:right}

Should be:

.test{text-align:right;margin-right:10px;float:left}
.test_right{text-align:right;border-left:0px;border-right:1px}
.test_left{float:left}

I have the following preg_replace, but it only matches 1 instance in each {} and I need it to match all instances.

$css = preg_replace('/({.*?)left(.*?})/i', '$1right$2', $css);

The other problem with this is that I can't swap left and right because everything would be right after I run the first preg_replace. How could I solve that issue? Perhaps using preg_replace_callback?


Solution

  • I was able to successfully figure it out.

    function callback($match)
    {
        $matchit = strtr($match[0], array('left' => 'right', 'right' => 'left'));
        return $matchit;
    }
    
    $css= preg_replace_callback('/{(.*?)}/i', 'callback', $css);
    echo $css;
    

    The preg_replace_callback is returning anything between { and }. The callback function is replacing left and right.

    I am further refining this function to add some kind of ignore trigger so the PHP will ignore certain classes/IDs. Also, it will need to do some reversing on padding and margin, among other things. The entire thing will be made into a class for anyone using PHP to convert CSS to RTL easily.

    Update:

    You can use this preg_replace instead:

    $css = preg_replace_callback('/{(?!\/\*i\*\/)(.*?)}/i', 'callback', $css);
    

    Then you can put /*i*/ into any line you want it to ignore. For example:

    .test{/*i*/margin-left:0px;text-align:right}