ubuntu - línea de comando - lista de patrones que se eliminarán del archivo

CorePress2023-09-17  2

Para ilustrarlo más tenemos dos contenidos de archivo:

archivo1

hello
1_hello 
2_hello
world
1_world
2_world
hello1
1_hello1
2_hello1
world1
1_world1
2_world1

archivo2

This
hello
1_hello
2_hello
is world
1_world
2_world
my
hello1
1_hello1
2_hello1
word
world1
1_world1
2_world1
file 

lo que quiero es iterar la primera columna del archivo1 y eliminar las entradas que coinciden en el archivo2 y producir un resultado como:

This
is
my 
word
file

¿Cómo puedo proceder?



------------Respuesta------------

Quieres usar awk para leer el archivo1 y recordar todas sus palabras. Luego lea el archivo 2 y genere las palabras que no se vieron en el archivo 1:

gawk -v RS='[[:space:]]+' 'NR==FNR {words[]=1; next} !( in words)' file1 file2

Eso utiliza cualquier secuencia de espacios en blanco como separador de registros, por lo que cada palabra se trata como una "línea" separada. Este awk ahora es específico de GNU, pero es el awk predeterminado en Ubuntu


  • Es simplemente fantástico, ¡gracias por compartir este conocimiento! -postre 20 de septiembre de 2017 a las 18:05
  • @dessert: si quieres una respuesta aún más elegante, mira la mía. ;-P - David Foerster 2 de octubre de 2017 a las 10:19


------------Respuesta------------

Puedes usar grep -f FILE para obtener patrones de un archivo FILE. En su caso, recomiendo algunos indicadores adicionales (consulte la explicación a continuación) para la siguiente invocación final de grep:

grep -v -x -F -f file1 -- file2
  • -f ARCHIVO: obtiene patrones del ARCHIVO, uno por línea.

  • -F: interpreta el patrón como una lista de cadenas fijas, separadas por nuevas líneas, cualquiera de las cuales debe coincidir.

  • -x: selecciona solo aquellas coincidencias que coincidan exactamente con toda la línea. (Es posible que desee eliminar esta opción si desea permitir líneas parcialmente coincidentes).

  • -v: invierte el sentido de coincidencia para seleccionar líneas que no coinciden.

Fuente: la documentación de GNU grep o, alternativamente, su página de manual

Todas las opciones utilizadas anteriormente están especificadas por POSIX y no requieren extensiones GNU.


  • ¡Realmente elegante! +1 ;) -postre 2 de octubre de 2017 a las 10:53


------------Respuesta------------

Esta línea de comando debería funcionar:

while read -r word; do sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; done < file1

Después de ejecutar el comando anterior, el archivo de salida, archivo2, debería verse así:

This
is
my
word
file

Versión más legible de la línea de comando anterior:

while read -r word; do \
    sed -e "s/\<$word\>//g" -e '/^\s*$/d' file2 -i; \
done < file1

El bucle while lee el archivo línea por línea - < archivo1. El valor de cada línea se utiliza como valor de la variable creada temporalmente, llamada $palabra - -r palabra. Esta variable se usa como argumento dentro del comando sed y se sustituye [s] por un valor en blanco en el archivo2, la primera expresión: "s/\<$word\>//g" = s/<source_value> ;/<valor_reemplazo>/g. La bandera g significa: aplicar el reemplazo a todos los partidos. Luego, si hay una línea en blanco dentro del archivo, se elimina: la segunda expresión: '/^\s*$/d'.

Necesitamos usar la sintaxis \<...\>para encontrar solo las coincidencias exactas. Necesitamos comillas dobles - "..." - para la primera expresión porque $word es el nombre de una variable y queremos expandirlo como su valor dentro del comando sed.

La opción -i significa que los cambios se realizarán en sus lugares dentro del archivo de destino: archivo2. Si se elimina esta opción, el resultado se enviará a la salida estándar pero no será significativo. La opción -i.bak no es aplicable a este escenario, porque el archivo de destino se sobrescribirá muchas veces, por lo que debes crear una copia de seguridad con anticipación.




------------Respuesta------------

Utilice grep con el indicador -v (invertir).

Al usar expresiones regulares extendidas (-E), puede crear una lista de patrones separados por | que desea excluir, p. patrón1|patrón2|patrón3:

grep -v -E "^[0-9]|world|hello" file


------------Respuesta------------

Aunque los criterios de eliminación no están muy claros, supongo que las partes a eliminar son (www\n1_www\n2_www) para todas las palabras www (corríjame si me equivoco)

Usando (gnu)sed:

sed -zr 's/(\w+)\n1_\n2_\n//g' ex