Заменить кратчайшее совпадение строкового рисунка

У меня есть эта строка:

update mytable set mycol=myvalue where mycol=yourvalue; 

Мне нужно преобразовать его в:

 insert into mytemp select * from mytable where mycol=youvalue; 

Я могу сделать это так, и это работает отлично:

 sed -e 's/^Update.*where//ig' -e "s/^/insert into mytemp select * from mytable where /g" n.txt 

НО :

Если строка:

 update mytable set mycol=myvalue where mycol=(select yourcol from yourtable where youcol=yourvalue); 

Я получил:

 insert into mytemp select * from mytable where youcol=yourvalue); 

В то время как я хочу:

 insert into mytemp select * from mytable where mycol=(select yourcol from yourtable where youcol=yourvalue); 

Что я могу сделать?

2 Solutions collect form web for “Заменить кратчайшее совпадение строкового рисунка”

По умолчанию двигатель regex от sed жадный. Это означает, что шаблон всегда соответствует максимально возможному совпадению. Вы должны сделать не жадный поиск, но я думаю, что sed не поддерживает не жадные поиски. Поэтому вы должны добавить опорную точку (ы) к вашему шаблону поиска, чтобы sed нашел кратчайшее возможное совпадение.

Следующая строка пытается подражать нежелательному соответствию для вашего особого случая, и это не требует универсальности, так как один параметр w между update и первый, where делает шаблон недействительным:

 sed -e 's/^Update[^w]*where//ig'\ -e "s/^/insert into mytemp select * from mytable where /g" n.txt 

Другие regex-engine поддерживают эту функцию, например, например, perl и awk .

Но в вашем случае я думаю, что это выражение

 sed -e 's/^Update.\+where\(.\+where.*\)$/\ insert into mytemp select * from mytable where \1/ig' n.txt 

было бы более удобным, связанным с вашей конкретной проблемой.

(трейлинг \ в строках выше добавляется только для того, чтобы сделать строки более разборчивыми.)

Согласование регулярных выражений выполняется слева направо и с самым длинным совпадением. Следовательно, ^Update.*where соответствует последнее вхождение, where на линии.

Один из способов сделать это совпадение – использовать не-жадный квантификатор для * . Сед не поддерживает не жадные кванторы, но perl делает.

 perl -pe 's/^update.*?where//i; s/^/insert into mytemp select .*? from mytable where /' 

Другой способ, который может или не может соответствовать вашим данным, – это отклонить круглые скобки в настройках имени таблицы и столбца.

 sed -e 's/^update[^()]*where//i' -e 's/^/insert into mytemp select [^()]* from mytable where /' 

Более сложный метод заключается в том, чтобы сначала заменить первый, where уникальным маркером, затем сделать свою замену и, наконец, повернуть маркер where . Поскольку sed работает по строкам, строка гарантированно не содержит символ новой строки, представленный \n в sed.

 sed -e 's/ where /\n/' \ -e 's/^update.*$//i' -e 's/^/insert into mytemp select .* from mytable where /' \ -e 's/\n/ where/' 
  • Извлечь два значения из вывода команды
  • Заменить шаблон в файле с шаблоном во втором файле
  • Может ли grep выводить только указанные группы, которые соответствуют?
  • sed count lines между шаблоном - несколько файлов
  • Получить строку запроса из URL-адресов в файле журнала
  • Искать текст в Linux, но не отображать полную строку в результатах
  • Извлечение частей текста с помощью sed, awk
  • Удалите все повторяющиеся слова из строки, используя сценарий оболочки
  • Необходимо вставить одинарные кавычки в текстовый файл для использования в качестве SQL-запроса с помощью sed
  • Как вставить текст в качестве альтернативы из двух файлов с общим шаблоном
  • Катить все файлы в папке, включая имя файла, используя цикл for?
  • добавьте% 200 в конце строки «адрес 1.1.1.1»
  • Linux и Unix - лучшая ОС в мире.