Помогите решить следующую проблему. Удалить все пары символов \
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...