Encuentre el patrón y elimínelo de todos los archivos

Encuentre el patrón y elimínelo de todos los archivos

Por favor ayúdenme a resolver el siguiente problema. Elimine todos los pares de caracteres \ nde Test_Macro en todos los archivos. Consulte el siguiente ejemplo:

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/Archivo2.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:

Archivo1.txt

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

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

dir1/Archivo2.txt

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

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

Cualquier ayuda o sugerencia es muy apreciada. Estoy pensando en escribir un guión. Porque tengo muchos tipos diferentes de archivos y muchas macros de este tipo. ¡Gracias de antemano!

Los argumentos de Test_Macro pueden tener llamadas anidadas a otras macros y pueden tener caracteres dentro de cadenas.

Respuesta1

Hay una frase que conviene recordar: "las expresiones regulares no se pueden contar".

Esto es importante en este caso porque muchas herramientas Unix "simples" se basan en expresiones regulares. El conteo aquí consiste en contar los paréntesis de apertura y cierre ('paréntesis') que podrían usarse dentro de los argumentos de Test_Macro.

Si las llamadas a Test_Macronuncatienen paréntesis anidados, entonces existe un truco sencillo. Primero cambie cada )carácter a una nueva línea y viceversa. Luego elimine todas las líneas que no contengan Test_Macro y elimine todo hasta Test_Macro. En este punto, una parte del File2.txt procesado se vería así

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

Entonces ahora necesitamos convertir la )espalda. En este punto tienes un par de opciones. Prefiero usar sed para deshacerme de los espacios adicionales al mismo tiempo. También necesitamos volver a agregar el )y tal vez el;

Juntando esto, tenemos

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

Si existe la posibilidad de que los argumentos de Test_Macro incluyan paréntesis anidados, entonces necesita sacar armas significativamente más grandes, ya que necesita analizar la entrada en lugar de simplemente hacer coincidir el patrón. (En teoría, si puede restringir el nivel de anidamiento, entonces puede hacer coincidir el patrón, pero en la práctica esto se vuelve muy, muy complicado y muy rápidamente y debe descartar este enfoque). Existen marcos de análisis para lenguajes como Python, o puede crear herramientas sobre herramientas como Lex.

Respuesta2

Editar: esta respuesta se preparó antes de que se revisara la pregunta. La forma original de la pregunta incluía:

Cuando intenté encontrar algún patrón usando "grep", solo imprime la primera línea. Pero quiero hasta el final del soporte.

Las expresiones regulares no pueden contar, pero Sed puede realizar un bucle.

Aquí hay un fragmento de Sed que se tomará de cualquier línea que contenga Test_Macrola línea con el par cercano apropiado,incluso si hay paréntesis anidados:

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

Convertido a una sola línea, esto se ve así:

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

La entrada y la salida se ven así:

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

Respuesta3

Archivo1:

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

Archivo2:

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

PD: la forma más sencilla de eliminar todos los saltos de línea es;

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

sin saltos de línea;

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

sin "\n" pero con saltos de línea... jajaja

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

simplemente eliminando la cadena "\n" (y el espacio final);

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

una vez más (con suerte, la última vez)... eliminando la cadena "\n" cuando está en la función Test_Macro, pero no fuera, y sin eliminar los saltos de línea;

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

actualizar;

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

información relacionada