Я сталкиваюсь с геркулесовой задачей в многострочном поиске и замене (объяснено в отдельных частях).

Решение я ищу включает в себя использование регулярных выражений в Notepad++ либо встроенный Find & Replace или с поиском многострочного и заменить диалог доступен на NPPtoolbucket плагин.

Это пример извлечения входного файла:

ALPHA('Hello John')
IGNORE111
IGNORE222
BETA('Hi Mary') 

Мне нужно заменить Привет Мэри (четвертая строка) на Привет Джон (контент извлекается из первой строки). т.е. фактический контент в четвертой строке между BETA ('и') должен быть заменен контентом, полученным между ALPHA ('и') из первой строки.

Желаемый результат должен быть:

ALPHA('Hello John')
IGNORE111
IGNORE222
BETA('Hello John')

Проблема, с которой я сталкиваюсь, заключается в том, что у меня 47 файлов IFC (по 12000 строк в каждом). Эти файлы имеют имя сборки в первой строке (уникальное для каждого файла IFC), и его необходимо использовать для замены содержимого где-то в строках 48, 87 и во многих других строках во всех 47 файлах IFC. Все идет по определенному шаблону. Можете ли вы предложить какой-нибудь трюк для достижения этого с помощью регулярных выражений?

Скажи как - найти с помощью (ALPHA\(')(.*)(')(NEW_SYNTAX_I_SEEKING)(BETA\(')(.*)(')

и заменить на \1\2\3\4\5\2\7

где

(ALPHA\(') станет ref \1

(.*) будет возвращен ref \2 , он будет разделен как -> Hello John

(') вернется ref \3

(NEW_SYNTAX_I'M_SEEKING) вернется назад ref \4 ; это будет новый синтаксис регулярных выражений, который я ищу, который будет извлекать контент, распределенный по нескольким строкам, и тот, который я не хочу никаких изменений

(BETA\(') станет ref \5

(.*) станет back ref \6 , он будет разделен как -> Привет, Мэри, поэтому мы можем использовать back ref \ 2 для замены back ref \6 .

(') вернется ref \7

Надеюсь, я правильно сформулировал свой вопрос и намерение. Я высоко ценю любую помощь, оказанную.

Ура, JJ

2 ответа2

0

Следующий ответ отредактирован - так как желательно использовать $ вместо \, когда у нас более 9 обратных ссылок

Небольшая настройка с информацией, собранной на форумах, помогла мне.

Решение довольно простое (хитрость в шаге 2)

1) Открыть встроенный Find & Replace в блокноте ++

2) убедитесь, что вы проверили:

[]. соответствует новой строке

3) В поиске чего, наберите

(АЛЬФА \ (') (. *) ('\)) (. *) (БЕТА \ (') (.*) ('))

Примечание - пробелы приведены выше для ясности. Между ними вообще нет пробелов, и они должны быть удалены

4) Вместо, введите

$ 1 $ 2 $ 3 $ 4 $ 5 $$ 2 $ 7

5) нажмите "заменить" / "заменить все" / "заменить все во всех открытых документах" в соответствии с вашими потребностями.

Бинго!

объяснение

(ALPHA \ (') вернется назад ref $ 1

(. *) будет возвращен ref $ 2, он будет разделен как -> Привет Джон

('\)) вернётся ref $ 3

(. *) вернется назад ref $ 4; Это будет извлекать контент, распределенный по нескольким строкам, и тот, который я не хочу никаких изменений

(BETA \ (') вернётся ref $ 5

(. *) будет возвращать ref $ 6, он будет делиться на -> Привет, Мэри, поэтому мы можем использовать back ref 2 для замены back ref 6.

('\)) вернётся ref $ 7

0

Если вы много работаете с текстовыми файлами, вам понравится awk .

awk -i inplace 'NR==1 && match($0, /.*\('\''(.+)'\''\)/,matches) {name = matches[1]; print $0} /IGNORE/ {print $0} NR>1 && !/IGNORE/ {print gensub (/([\w ]*\('\'').+('\''\))/, "\\1"name"\\2", "1")}' *.txt

Объяснение займет некоторое время, позвольте мне сначала разбить команду на три части, каждая из которых состоит из условия и команды:

  • NR==1 && match($0, /.*\('\''(.+)'\''\)/,matches) {name = matches[1]; print $0} это печатает первую строку и копирует то, что в вашем случае является именем сборки, в переменную, называемую просто name .
  • /IGNORE/ {print $0} если строки соответствуют тексту IGNORE , просто напечатайте их.
  • NR>1 && !/IGNORE/ {print gensub (/([\w ]*\('\'').+('\''\))/, "\\1"name"\\2", "1")} выполнить regex replace в оставшихся строках, используя переменную name созданную ранее.

Далее следует еще несколько деталей:

awk это инструмент для работы с текстовыми файлами, в качестве альтернативы я бы порекомендовал perl .

-i inplace это означает, что исходные файлы будут редактироваться (делать резервные копии!). Отказ от ответственности: я не смог протестировать этот параметр, потому что для него требуется более новая версия awk чем та, которую я установил.

' является строкой, поэтому она инкапсулирует в апострофах.

NR==1 это условие, номер строки должен быть 1 .

&& это означает И.

match( это еще одно условие, которое должно быть выполнено: функция соответствия regexp, которая принимает 3 аргумента.

$0 первый аргумент: это представляет всю строку.

/.*\('\''(.+)'\''\)/ второй аргумент, регулярное выражение

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

{ здесь начинаются действия, которые должны быть выполнены в случае выполнения условий.

name = matches[1] name переменной создается, и оно назначается равным первой группе захвата (аналогично обратной ссылке \1).

; точка с запятой отделяет инструкции.

print $0 мы печатаем и первую строку.

/IGNORE/ искать строки, содержащие текст IGNORE .

{print $0} просто напечатайте их.

NR>1 && !/IGNORE/ условие: для всех строк, кроме первой, если они не содержат текст IGNORE .

{print распечатать результат замены. gensub ( функция, выполняющая поиск и замену, позволяющая использовать обратные ссылки.

/([\w ]*\('\'').+('\''\))/ шаблон поиска. Здесь последовательность '\'' - это то, что нужно для вставки одного ' .

"\\1"name"\\2" шаблон замены. "\1" и "\2" являются двумя обратными ссылками.

"1" означает, что заменяется только первое совпадение.

' команды awk

*.txt запускает awk для всех файлов с расширением .txt в текущем каталоге.

Примечание: я знаю, что вы спрашиваете, как это сделать в Notepad++, но я считаю, что вы должны рассмотреть инструменты командной строки. Причина в том, что графические программы более склонны выполнять одноразовую операцию, но в комментарии вы указываете, что хотите автоматизировать работу и обрабатывать 47 файлов одновременно. Командная строка больше подходит для автоматизации, чем для графических интерфейсов, это моя точка зрения.

Для начала у вас есть gawk (GNU awk) для Windows, и если вы хотите продолжить, вы можете работать в Linux или установить Linux-подобную среду, такую как Cygwin.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .