Составить регулярное выражение для нахождения единичного или повторяющегося символа X в тексте, обрамленном с обеих сторон символом Y

Предположим, необходимо найти символы нижнего подчеркивания _ в следующих строках:

"last_sql_error"
"wrong_type_conversion_from"

Решить эту задачу с помощью positive lookbehind достаточно просто:

(?<=".+)_(?=.+")

Однако данный оператор не поддерживается в большой части движков. Как решить эту задачу без использования вышеуказанного оператора?

UPD: Конкретизирую задачу. Есть текст, в нем встречаются участки, обрамленные кавычками ". Символом, разделяющим слова в этих участках является не пробел, а _. Так вот именно в участках текста, обрамленных кавычками я хочу заменить _ на пробел. Пример исходного текста:

Я вышел на улицу и увидел на здании вывеску "магазин_продуктов", пройдя_чуть_дальше_увидел_вывеску "посторонним_вход_воспрещен"

Пример результирующего текста:

Я вышел на улицу и увидел на здании вывеску "магазин продуктов", пройдя_чуть_дальше_увидел_вывеску "посторонним вход воспрещен"

То есть, я хочу открыть этот текст к примеру в notepad++, найти все такие нижние подчеркивания с помощью регулярного выражения и заменить их.


Ответы (1 шт):

Автор решения: Wiktor Stribiżew

Тот факт, что у вас слева и справа одинаковый разделитель ("), усложняет задачу.

Если принять во внимание то, что между кавычками могут находиться только букво-цифровые символы или символы нижнего подчёркивания, в Notepad++ вы можете использовать

(?:\G(?!^)|")[^\W_]*\K_(?=\w*")

См. пример использования регулярного выражения. Подробности:

  • (?:\G(?!^)|") - конец предыдущего совпадения или символ "
  • [^\W_]* - букво-цифровые символы, 0 и более повторов (кроме _)
  • \K - обнуление буфера памяти текущего совпадения
  • _ - символ нижнего подчёркивания
  • (?=\w*") - блок предварительного просмотра вперёд, требующий наличия нуля и более букво-цифровых символов или символов нижнего подчёркивания, сразу после которых идёт символ ".

В более общем случае, в обычных языках программирования, следует воспользоваться функцией в качестве параметра замены. Например, в JavaScript:

const text = 'Тек_ст "last_sql_error" и_ "** (wrong0)_(type) | [conversion]_from" ту_т';
console.log(text.replace(/"[^"]*"/g, (x) => x.replace(/_/g, ' ')));

→ Ссылка