¿Cómo puedo eliminar la quinta palabra de cada línea en un archivo?

13

Quiero eliminar la quinta palabra de cada línea en un archivo.

El contenido actual del archivo:

File is not updated or and will be removed  
System will shut down f within 10 seconds  
Please save your work 55 or copy to other location  
Kindly cooperate with us D  

Rendimiento esperado:

File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
pmaipmui
fuente

Respuestas:

31

Que tal cut:

$ cut -d' ' -f1-4,6- file.txt 
File is not updated and will be removed  
System will shut down within 10 seconds  
Please save your work or copy to other location  
Kindly cooperate with us
  • -d' ' establece el delimitador como espacio

  • -f1-4,6- selecciona el primer al cuarto campo (palabra), dejando el quinto y luego continúa imprimiendo del sexto al resto.

heemayl
fuente
11

Una solución con cut:

cut -d ' ' -f1-4 -f6- FILE
fd0
fuente
Múltiple -fno es compatible en mi cut(GNU) al menos ..
heemayl
Compatible con BSD cut pero me gusta su respuesta mejor que la mía.
fd0
1
Si se trata de corte de GNU, se obtiene la --complementbandera de simplificar las cosas: cut --complement -d ' ' -f5. Recuerde redirigir la salida a un nuevo archivo, luego mvsobre el original.
Toby Speight
6

awk: elimina el quinto campo

awk '{for (i=5; i<NF; i++) $i = $(i+1); NF--};1' file

Si desea guardar el archivo en su lugar: /programming//q/16529716/7552

Simplemente podría borrar el contenido del quinto campo, pero eso deja 2 separadores de campo de salida consecutivos:

awk '{$5 = ""};1' file
Glenn Jackman
fuente
La advertencia aquí es que cambiar el valor de cualquier campo en awk tiene el efecto secundario de reescribir todo el "$ 0" con solo 1 separador entre cada campo. debe tenerse en cuenta si desea mantener cualquier alineación (a menos que gnu awk tenga una opción para evitar esto? awk / nawk regular volverá a calcular $ 0)
Olivier Dulac
En ambos casos, reformatea la línea con un solo separador. Si hay 2 espacios o espacio + pestaña en un separador, el resultado es un espacio único en su lugar. Con suerte, esto está bien para la mayoría del texto.
NeronLeVelu
4

Con POSIX sed:

sed -e 's/[^[:alnum:]_][[:alnum:]_][[:alnum:]_]*//4' <file
Cuonglm
fuente
¿por qué limitar la clase a: alnum: _ y no a nada más entonces :blank:o :space:?
NeronLeVelu
@NeronLeVelu: Eso depende de cómo se defina qué hace una palabra.
Cuonglm
@mikeserv; ¡Buena atrapada! Actualicé mi respuesta.
Cuonglm
¿Para qué es el \(grupo de captura \)?
mikeserv
@mikeserv: mi error al escribir, acabo de intentar algunas formas de retener el delimitador.
Cuonglm
2

Glenn ofreció una solución que es equivalente a

awk '{$ 5 = ""; imprimir} ' archivo

Como él y otros han señalado, esto

  1. elimina espacios en blanco iniciales y finales de cada línea,
  2. comprime cada cadena de espacios en blanco (espacios y / o pestañas) en un solo espacio, y
  3. deja dos espacios entre la cuarta y seis palabras.

Un truco para solucionar el tercer problema es

awk '{$ 5 = ""; imprimir} ' archivo | sed 's / / /'

Esto aún dejará uno o más espacios agregados al final de cualquier línea que tenga cinco o menos palabras. Si puede identificar una palabra que nunca aparecerá en la entrada,

awk '{$ 5 = "unicornio"; imprimir} ' archivo | sed 's / * unicornio //'

manejará incluso eso (pero aún deja los problemas 1 y 2).

Scott
fuente
2
 sed 's/^\(\([[:blank:]]*[^[:blank:]]\{1,\}\)\{4\}\)[[:blank:]]*[^[:blank:]]*/\1/' YourFile > Output.txt
  • posix sed basado en espacio / separador de tabulación (metaclase [: en blanco:]])
  • mantenga el siguiente espacio después de la quinta palabra pero elimine el anterior

Una *versión más robusta (toma el patrón más largo posible y el patrón con podría perder la separación o la palabra en la primera versión) pero una versión un poco más larga

sed 's/^\([[:blank:]]*\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{4\}\[^[:blank:]]\{1,\}/\1/' YourFile > Output.txt
NeronLeVelu
fuente
1
sed 's/[^[:blank:]]*//5'
mikeserv
@mikeserv, esto mantendrá ambos separadores circundantes, sed 's/[[:blank:]*[^[:blank:]]*//5'es mejor. Muy buen punto. Sospeché que tomaría cada carácter individual como una entidad, pero tomaría el mayor patrón sin romper como entidad
NeronLeVelu
sed 's/[[:blank:]][^[:blank:]]*//4'eliminará el quinto campo por completo.
mikeserv
@mikeserv Suponiendo que no haya espacio inicial en la línea (como en la muestra)
NeronLeVelu
En este caso, sí, creo que tienes razón. Por lo general, tal cosa sería un campo nulo y el comportamiento sería correcto. En este caso se debe hacer como hicieron @cuonglm y garantizar se hace referencia a una palabra cada vez que como sed 's/[[:blank:]][^[:blank:]][^[:blank:]]*//4', o, w / GNU / BSD / toybox seds: sed -E 's/[[:blank:]][^[:blank:]]+//4'.
mikeserv
1

Perl.

perl -ne 'print $_ =~ /^(\w+ +\w+ +\w+ +\w+ +)\w+ (.*)/,"\n"' file
Steve
fuente
1

Otra posibilidad, suponiendo un corte GNU:

cut -d' ' -f5 --complement file.txt
Trauma digital
fuente
-1

Usando Perl> 5.10 (y generando correctamente todas las líneas: 0)): -

perl -nE '/^((\w+ +){4})\w+ *(.*)/; say $1.$3' file
Medlock Perlman
fuente