Найти шаблон и удалить его из всех файлов

Найти шаблон и удалить его из всех файлов

Помогите решить следующую проблему. Удалить все пары символов \ nиз Test_Macro во всех файлах. Смотрите пример ниже:

Fil1.txt

Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n");
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...

dir1/Файл2.txt

Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n",
        123456);
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...

Ожидаемый результат:

Файл1.txt

Test_Macro(abc, def, " string1 string2 test string",
   "test string2 ");
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...

dir1/Файл2.txt

Test_Macro(abc, def, " string1 string2  test string",
   "test string2 ",
    123456);
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...

Любая помощь или предложения будут высоко оценены. Я планирую написать скрипт. Поскольку у меня много разных типов файлов и много таких макросов. Спасибо заранее!

Аргументы Test_Macro могут иметь вложенные вызовы других макросов и могут содержать любые символы внутри строк.

решение1

Есть фраза, которую следует запомнить: «регулярные выражения не умеют считать».

Это важно в данном случае, поскольку множество «простых» инструментов unix основаны на регулярных выражениях. Подсчет здесь заключается в подсчете открывающих и закрывающих скобок («круглых скобок»), которые могут использоваться внутри аргументов Test_Macro.

Если вызовы Test_Macroникогдаесть вложенные скобки, тогда есть простой трюк. Сначала замените каждый )символ на новую строку, и наоборот. Затем удалите каждую строку, которая не содержит Test_Macro, и удалите все до Test_Macro. На этом этапе часть обработанного File2.txt будет выглядеть так

Test_Macro(abc, def, " string1 string2 test string",)   "test string2 ",)    123456

Итак, теперь нам нужно преобразовать )back. На этом этапе у вас есть несколько вариантов. Я предпочитаю использовать sed, чтобы избавиться от лишних пробелов одновременно. Нам также нужно добавить back в )и, возможно,;

Собирая все это вместе, мы имеем

find . -type f | while read -r fn
do
   < "$fn" tr ')\n' '\n)' | sed -n 's/.*Test_Macro(/Test_Macro(/p' | \
     sed 's/) */ /g;s/$/);/'
done

Если есть вероятность, что аргументы Test_Macro включают вложенные скобки, то вам нужно вытащить значительно более крупные пушки, так как вам нужно разобрать входные данные, а не просто сопоставить их с образцом. (Теоретически, если вы можете ограничить уровень вложенности, то вы можете сопоставить их с образцом, но на практике это очень и очень быстро становится сложным, и вам следует отказаться от этого подхода). Существуют фреймворки парсеров для таких языков, как python, или вы можете создавать инструменты поверх таких инструментов, как lex.

решение2

Редактировать: Этот ответ был подготовлен до того, как вопрос был пересмотрен. Первоначальная форма вопроса включала:

Когда я попытался найти какой-то шаблон с помощью "grep", он вывел только первую строку. Но мне нужно до конца скобок.

Регулярные выражения не умеют считать, но Sed умеет циклить.

Вот фрагмент Sed, который выберет любую строку, содержащую Test_Macroстроку с соответствующей закрывающей скобкой,даже если есть вложенные скобки:

#n
/Test_Macro/{
  p;
  :rep
  s/([^()]*)//;
  trep
  /^[^(]*$/d;
  h;
  n;
  p;
  x;
  G;
  brep
}

Преобразованное в однострочный текст, это выглядит так:

sed -n -e '/Test_Macro/{p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}'

Ввод и вывод выглядят так:

$ cat temp 
Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n");
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...
$ sed -n -e '/Test_Macro/{p;:rep' -e 's/([^()]*)//;trep' -e '/^[^(]*$/d;h;n;p;x;G;brep' -e '}' temp 
Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n");
Test_Macro(asdsadas, "test String1");
$ 

решение3

Файл1:

$ sed '/Test_Macro/{N;$!N;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n");
Test_Macro(asdsadas, "test String1");

Файл2:

$ sed '/Test_Macro/{N;$!N;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc2.txt
Test_Macro(abc, def, "\n string1 string2 \n test string",
       "test string2 \n",
        123456);
Test_Macro(asdsadas, "test String1");

ps, самый простой способ удалить все переносы строк:

echo -e "line \n break" | tr "\n" " "

без переносов строк;

$ sed ':a;N;$!ba;s/[^;]\n[ ]*/ /g;' abc2.txt  | grep Test_Macro
Test_Macro(abc, def, "\n string1 string2 \n test string" "test string2 \n" 123456);
Test_Macro(asdsadas, "test String1");

без "\n", но с переносами строк... лол

$ sed '/Test_Macro/{N;$!N;s/[ ]*\\n//g;s/.*\(Test_Macro[^)]*);\).*/\1/;p;};d' abc2.txt
Test_Macro(abc, def, " string1 string2 test string",
       "test string2",
        123456);
Test_Macro(asdsadas, "test String1");

просто удаляем строку "\n" (и конечный пробел);

$ sed ':a;N;$!ba;s/\\n[ ]*//g;' abc2.txt
Test_Macro(abc, def, "string1 string2 test string",
       "test string2 ",
        123456);
// Some code or text

Test_Macro(asdsadas, "test String1");
// Some code...

еще раз (надеюсь, в последний раз)... удаление строки "\n" внутри функции Test_Macro, но не снаружи, и не удаление переносов строк;

$ sed '{N;/Test_Ma/{s/[ ]*\\n//g;};s/\(Test_Macro[^)]*);\)/\1/};' abc2.txt
Test_Macro(abc, def, " string1 string2 test string",
       "test string2",
        123456);
// Some code or text \n

Test_Macro(asdsadas, "test String1");
// Some code...

обновлять;

$ sed '{:a;N;/Test_Ma/{s/[ ]*\\n//g;};ta};' abc2.txt 
Test_Macro(abc, def, " string1 string2 test string",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
       "test string2",
        123456);
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n
// Some code or text \n

Test_Macro(asdsadas, "test String1");
// Some code...

Связанный контент