¿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

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.


11

Una solución con cut:

cut -d ' ' -f1-4 -f6- FILE

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

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

¿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).


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

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


-1

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

perl -nE '/^((\w+ +){4})\w+ *(.*)/; say $1.$3' file
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.