Regex, чтобы соответствовать пробелу, но пропустить разделы - PullRequest
4 голосов
/ 13 мая 2011

Я понимаю, так как Regex по существу не имеет состояния, довольно сложно добиться сложных совпадений, не прибегая к дополнению логики приложения, однако мне любопытно узнать, возможно ли следующее.

Совпадение всех пробелов, достаточно просто: \s+

Но пропустите пробел между определителями, в моем случае <pre> и </pre> слово nostrip.

Есть ли какие-нибудь хитрости для достижения этой цели?Я думал о двух разных матчах, один для всех пробелов и один для <pre> блоков ноздрейных секций , и как-то отрицал последние из первых.

"This is some text NOSTRIP this is more text NOSTRIP some more text."
// becomes
"ThisissometextNOSTRIP this is more text NOSTRIPsomemoretext."

Вложение данных тегов разделов ноздри не имеет значения, и я не пытаюсь проанализировать дерево HTML или что-либо еще, просто приведя в порядок текстовый файл , но сохранив пробелы в <pre> блоках разделах ноздри по понятным причинам.

( лучше? )


Это в конечном счете то, с чем я столкнулся.Я уверен, что он может быть оптимизирован в нескольких местах, но пока он работает хорошо.

public function stripWhitespace($html, Array $skipTags = array('pre')){
    foreach($skipTags as &$tag){
        $tag = "<{$tag}.*?/{$tag}>";
    }
    $skipped = array();
    $buffer = preg_replace_callback('#(?<tag>' . implode('|', $skipTags) . ')#si',
        function($match) use(&$skipped){
            $skipped[] = $match['tag'];
            return "\x1D" . (count($skipped) - 1) . "\x1D";
        }, $html
    );
    $buffer = preg_replace('#\s+#si', ' ', $buffer);
    $buffer = preg_replace('#(?:(?<=>)\s|\s(?=<))#si', '', $buffer);
    for($i = count($skipped) - 1; $i >= 0; $i--){
        $buffer = str_replace("\x1D{$i}\x1D", $skipped[$i], $buffer);
    }
    return $buffer;
}

Ответы [ 2 ]

2 голосов
/ 13 мая 2011

Если вы используете язык сценариев, я бы использовал многоэтапный подход.

  • вытащить разделы NOSTRIP, сохранить в массив и заменить на маркеры (### или что-то)
  • заменить все пробелы
  • повторно ввести все сохраненные фрагменты NOSTRIP
1 голос
/ 13 мая 2011

Однажды я создал набор функций для уменьшения пробелов в выводах html:

function minify($html) {
        if(empty($html)) {
                return $html;
        }
        $html = preg_replace('/^(.*)((<pre.*<\/pre>)(.*?))?$/Ues', "parse('$1').'$3'.minify('$4')", $html);
        return $html;
}

function parse($html) {
        var_dump('1'.$html);
        // Replace multiple spaces with a single space
        $html = preg_replace('/(\s+)/m', ' ', $html);
        // Remove spaces that are followed by either > or <
        $html = preg_replace('/ ([<>])/', '$1', $html);
        $html = str_replace('> ', '>', $html);
        return $html;
}

$html = minify($html);

Возможно, вам придется немного изменить это, чтобы соответствовать вашим потребностям.

...