PHP RegEx для удаления двойных пробелов между двумя словами

Мне нужен Php-RegEx, чтобы найти все двойные пробелы между ключевым словом start и end и удалить их.

$teststring = 'This is a teststring ... :keyword_start: this is    the content    with double spaces :keyword_end: more text ... :keyword_start: this is the second   content    with double spaces :keyword_end: ... more text';

Мне нужен следующий результат:

This is a teststring ... :keyword_start: this is the content with double spaces :keyword_end: more text ... :keyword_start: this is the second content with double spaces :keyword_end: ... more text

Это то, что я пробовал: (но это не работает)

$teststring = preg_replace('#(:keyword_start:)\s\s+(:keyword_end:)#si', '', $teststring);

Может кто-нибудь помочь мне ?


person Integer    schedule 27.02.2016    source источник
comment
Попробуйте этот http://stackoverflow.com/questions/2368539/php-replacing-multiple-spaces-with-a-single-space   -  person Tim007    schedule 27.02.2016


Ответы (4)


Вы можете сделать это с таким шаблоном, используя якорь \G. Этот якорь соответствует положению после предыдущего совпадения (и началу строки по умолчанию). С его помощью вы можете получить смежные совпадения (пока вы не нарушите смежность):

$pattern = '~(?:\G(?!\A)|:keyword_start:\s)(?:(?!:keyword_end:)\S+\s)*+\K\s+~S';

$result = preg_replace($pattern, '', $str);

детали узора:

~             # pattern delimiter
(?:           # non-capturing group
    \G(?!\A)             # contiguous branch (not at the start of the string)
  |                      # OR
    :keyword_start:\s    # start branch
)
(?:
    (?!:keyword_end:)\S+ # all non-blank characters that are not the "end word"
    \s                   # a single space
)*+                   # repeat the group until a double space or the "end word"
\K                    # remove all on the left from the match result
\s+                   # spaces to remove
~S      # "STUDY" modifier to improve non anchored patterns

демонстрация

person Casimir et Hippolyte    schedule 27.02.2016

Вы можете использовать обратный вызов для того, что находится между словами.

$str = preg_replace_callback('/:keyword_start:(.*?):keyword_end:/s', function ($m) {
  return ':keyword_start:' . preg_replace('/\s{2,}/', " ", $m[1]) . ':keyword_end:';
}, $str);
  • (.*?) между токенами захватывает лениво любое количество любых символов до $1
  • \s{2,} соответствует двум или более пробелам
  • s флаг после закрывающего разделителя заставляет точку соответствовать новой строке

Смотреть демо на eval.in


Это можно было бы сделать с помощью одного изящного регулярного выражения, но оно более склонно к ошибкам, а объяснение занимает больше времени. Что-то типа

/(?::keyword_start:|\G(?!^)\S+)\K(?<!_end:)\s+/

Демо на regex101

person bobble bubble    schedule 27.02.2016

Ну, я плохо разбираюсь в php, поэтому я дам решение независимо от языка. Это будет полезно, так как вы можете выбрать свой язык и реализовать его аналогичным образом.

Итак, решение. Нет простого способа найти double space между двумя keywords. Может быть какое-то элитное регулярное выражение. Но мой подход довольно прост.

Шаг 1. Найдите текст между keywords с помощью (?<=:keyword_start:).*?(?=:keyword_end:).

Демонстрация Regex101 здесь.

Шаг 2. Замените double spaces или multiple tabs в найденном тексте на простой \s+.

Демонстрация Regex101 здесь.

person Community    schedule 27.02.2016

Если вы хотите, чтобы регулярное выражение заменяло все пробелы, включая вкладки и пустые строки, вы можете использовать это:

$s = preg_replace('/\s+/', ' ', $s);

Он заменит TAB и новую строку, даже если это только один, между символами. Несколько (любых) пробелов также будут уменьшены до одного символа пробела.

Здесь регулярное выражение только для нескольких пробелов (но в этом случае быстрее использовать str_replace, как в другом ответе здесь)

$s = preg_replace('/  */', ' ', $s);
person micropro.cz    schedule 27.02.2016