Замените подстроку, когда знаете только положение и структуру
У меня есть ситуация, когда у меня есть строка, которую я должен заменить определенные части. Я знаю, где находятся эти части и как они выглядят (другими словами, я могу сопоставить их с помощью регулярных выражений), но не только не знаю точное содержание, но и внутри строки могут быть похожие подстроки. Чего я хочу добиться, так это заменить только конкретное вхождение в это смещение, оставив остальное нетронутым.
Пример:
Test String (this) Test (not this) Test Test (this) Test Test (and this) Test (this maybe)
Я знаю, что должен заменить строки, которые соответствуют этому регулярному выражению: \(.*?\)
но только если они начинаются в позициях 12, 62 and 78
(другими словами, первый (this)
но не второй, (and this)
а также (this maybe)
, подстроки (not this)
а второй (this)
не подлежит замене)
Я знаю, что должен публиковать свои попытки решить эту проблему, но я смотрю на код с получаса, и из него ничего не вышло (я долго смотрел на код, прежде чем сдаться и спросить в прошлом, но сегодня я немного спешу) но у меня такое чувство, что решение проще, чем я думаю. Единственное, что я понял, это то, что я должен заменить строки в обратном порядке, чтобы не изменять позиции.
1 ответ
Вот что я придумал:
$string = 'Test String (this) Test (not this) Test Test (this) Test Test (and this) Test (this maybe)';
$offsets = [12, 62, 78];
$replace = "REPLACED";
// work backwards so we don't have to keep track of changing offsets
rsort($offsets);
foreach ($offsets as $offset) {
$string = preg_replace('/^(.{' . $offset . '})\([^\)]*\)/', '$1'.$replace, $string);
}
echo $string;
// Test String REPLACED Test (not this) Test Test (this) Test Test REPLACED Test REPLACED
Обратите внимание, что второй (this)
не был заменен, потому что он не начинается со смещения 12, 62 или 78. Этот на самом деле со смещением 45, если вы добавите его в $offsets
массив будет заменен также.
Я заметил в моих тестах, что \(.*\)
слишком широк для того, как я это решил, и я изменил его на \([^\)*\)
вместо этого (по существу: сопоставьте что-либо в скобках, если это не закрывающая скобка). Я должен был сделать это, потому что \(.*\)
также соответствует (this) Test (not this)
,