Encontre o padrão e remova-o de todos os arquivos

Encontre o padrão e remova-o de todos os arquivos

Por favor me ajude a resolver o seguinte problema. Remova todos os pares de caracteres \ nde Test_Macro em todos os arquivos. Por favor, veja o exemplo abaixo:

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/Arquivo2.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...

Resultado esperado:

Arquivo1.txt

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

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

dir1/Arquivo2.txt

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

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

Qualquer ajuda ou sugestão é muito apreciada. Estou planejando escrever algum roteiro. Porque tenho muitos tipos diferentes de arquivos e muitas dessas macros. Desde já, obrigado!

Os argumentos para Test_Macro podem ter chamadas aninhadas para outras macros e podem ter quaisquer caracteres dentro de strings.

Responder1

Há uma frase que deve ser lembrada: “expressões regulares não contam”.

Isso é importante neste caso porque muitas ferramentas Unix 'simples' são baseadas em expressões regulares. A contagem aqui é a contagem dos parênteses de abertura e fechamento ('colchetes') que podem ser usados ​​dentro dos argumentos para Test_Macro.

Se as chamadas para Test_Macronuncatêm parênteses aninhados, então existe um truque fácil. Primeiro mude cada )caractere para uma nova linha e vice-versa. Em seguida, exclua todas as linhas que não contenham Test_Macro e remova tudo até Test_Macro. Neste ponto, uma parte do File2.txt processado ficaria assim

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

Então agora precisamos converter as )costas. Neste ponto você tem algumas opções. Eu sou a favor de usar sed para se livrar dos espaços extras ao mesmo tempo. Também precisamos adicionar novamente o )e talvez o;

Juntando isso, temos

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

Se houver a possibilidade de que os argumentos para Test_Macro incluam parênteses aninhados, você precisará usar armas significativamente maiores, pois precisará analisar a entrada em vez de apenas combiná-la com o padrão. (Em teoria, se você pode restringir o nível de aninhamento, então você pode combinar padrões, mas na prática isso fica muito complicado muito rapidamente e você deve desconsiderar essa abordagem). Existem estruturas de analisador para linguagens como python, ou você pode construir ferramentas sobre ferramentas como lex.

Responder2

Editar: esta resposta foi preparada antes da pergunta ser revisada. A forma original da pergunta incluía:

Quando tentei encontrar algum padrão usando "grep", ele imprimiu apenas a primeira linha. Mas eu quero até o final da chave.

Expressões regulares não podem contar, mas Sed pode fazer loop.

Aqui está um trecho Sed que irá capturar qualquer linha que contenha Test_Macroa linha com o parêntese próximo apropriado,mesmo se houver parênteses aninhados:

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

Convertido para uma linha única, fica assim:

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

A entrada e a saída ficam assim:

$ 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");
$ 

Responder3

Arquivo1:

$ 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");

Arquivo2:

$ 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, a maneira mais fácil de remover todas as quebras de linha é;

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

sem quebras de linha;

$ 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");

sem "\n" mas com quebras de linha... haha

$ 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");

apenas removendo a string "\n" (e o espaço à direita);

$ 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...

mais uma vez (espero que seja a última vez)... removendo a string "\n" quando estiver na função Test_Macro, mas não fora, e não removendo quebras de linha;

$ 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...

atualizar;

$ 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...

informação relacionada