简体   繁体   中英

Regular expression replace whitespaces outside quotes (any)

Let's suppose I have this string:

this is a "test for stackoverflow", with 'single quotes too' and "combined 'quotes single and double'"

And I need to get:

thisisa"test for stackoverflow",with'single quotes too'and"combined 'quotes single and double'"

This was just an example, but quotes can be nested up to 3 levels (" str ' str " str " ' "), there may be also multiple lines. I need to get a RegEx to replace all the spaces outside quotes.

You can use this regex for this:

$s = <<< EOF
this is a "test for stackoverflow" , with 'single quotes too' and "combined 'quotes single and double'"
EOF;
echo preg_replace('/(?| *(".*?") *| *(\'.*?\') *)| +/s', '$1', $s);

OUTPUT:

thisisa"test for stackoverflow",with'single quotes too'and"combined 'quotes single and double'"

Simple (*SKIP)(*F) magic!

Use the following regex:

/(?:"[^"]++"|'[^']++')(*SKIP)(*F)|\s/

View a regex demo!

Expression explanation:

  • (?:"[^"]++"|'[^']++') Matches quotes and everything within the quotes.
  • (*SKIP)(*F) Skips the pointer to the next position and discard the match.
  • | OR (The following will only be matched if the above alternative does not discard this already
  • \\s Whitespaces.

Probably not the most elegant solution but it's a start (single-apostrophes that aren't meant as a quote aren't supported. Replace those before and replace them back later):

<?PHP
    $str = "this is a  \"test for stackoverflow\", with 'single quotes too' and \"combined 'quotes single and double'\"";

    $cleared = clearString($str);
    $solution = "thisisa\"test for stackoverflow\",with'single quotes too'and\"combined 'quotes single and double'\"";

    assert($cleared == $solution);

    function copyQuote($str, $until, $offset = 0)
    {
        $p = strpos($str, $until, $offset);

        if ($p !== FALSE)
            return substr($str, $offset, $p-$offset);
        else
            throw new Exception("Unclosed Quote Exception at position ".$offset);
    }

    function clearString($str)
    {
        $retVal = "";

        $len = strlen($str);
        for ($i = 0; $i < $len; $i++)
        {
            if ($str[$i] == "\"" || $str[$i] == "'")
            {
                $quote = copyQuote($str, $str[$i], $i+1);
                $retVal .= $str[$i].$quote.$str[$i];
                $i += strlen($quote)+1;
            } else {
                // Skip whitespaces outside of quotes, add any other check you'd like to do here
                if ($str[$i] != " " && $str[$i] != "\t")
                {
                    $retVal .= $str[$i];
                }
            }
        }
        return $retVal;
    }
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM