Quiero eliminar la última columna de un archivo txt, mientras que no sé cuál es el número de columna es. ¿Cómo puedo hacer esto?
Ejemplo:
Entrada:
1223 1234 1323 ... 2222 123 1233 1234 1233 ... 3444 125 0000 5553 3455 ... 2334 222
Y quiero que mi salida sea :
1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Comentarios
Responder
Con awk
:
awk "NF{NF-=1};1" <in >out
o:
awk "NF{NF--};1" <in >out
o:
awk "NF{--NF};1" <in >out
Aunque esto parece vudú, funciona. Hay tres partes para cada uno de estos comandos awk.
La primera es NF
, que es una condición previa para la segunda parte. NF
es una variable que contiene el número de campos en una línea. En AWK, las cosas son verdaderas si «no son 0 o una cadena vacía ""
. Por lo tanto, la segunda parte (donde NF
se reduce) solo ocurre si NF
no es 0.
La segunda parte (ya sea NF-=1
NF--
o --NF
) es simplemente restar uno de la variable NF
. Esto evita que se imprima el último campo, porque cuando cambia un campo (eliminando el último campo en este caso), awk
reconstruye $0
, concatena todos los campos separados por espacios de forma predeterminada . $0
ya no contenía el último campo.
La parte final es 1
. No es mágico, solo se usa como una expresión que significa true
. Si una expresión awk
se evalúa como verdadera sin ninguna acción asociada, la awk
acción predeterminada es print $0
.
Comentarios
- @JJoao: Ah, gracias, me olvidé de
--
. Una nota, actualmente, necesitas;1
para que sea compatible con POSIX. - Mi instinto inicial sería usar un bucle for, pero esto es mucho más conciso e inteligente.
- Es ' s vale la pena señalar que si ' estás usando un delimitador no predeterminado, ' Tendremos que hacer algunos cambios. Suponiendo que
,
es su delimitador:awk -F',' 'BEGIN { OFS = FS }; NF { NF -= 1 }; 1' < in > out
- El efecto de disminuir NF es un comportamiento indefinido de POSIX; obtendrá salida diferente según el awk que ' esté ejecutando. Algunos awks eliminarán el último campo como desee, otros no harán nada en absoluto y otros podrían informar un error de sintaxis o cualquier otra cosa.
Responder
Usando grep
con PCRE:
$ grep -Po ".*(?=\s+[^\s]+$)" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Usando GNU sed
:
$ sed -r "s/(.*)\s+[^\s]+$/\1/" file.txt 1223 1234 1323 ... 2222 1233 1234 1233 ... 3444 0000 5553 3455 ... 2334
Comentarios
- @ramin Seguro. . ¿Podrías preguntarlo como una nueva pregunta (así es como funciona este sitio) 🙂
- @ramin? ¿Te da alguna ¿restricción de tiempo o alguna advertencia?
- ¡Dice que esto está fuera de la pregunta estándar!
- @ramin Ok..permítame contactar a un administrador, tal vez ellos puedan ayudarlo con eso .. Por cierto, ¿revisó algún control de calidad anterior con respecto a su pregunta? Es posible que la pregunta ya se haya formulado y respondido.
- No ' t hagas preguntas súper básicas como " ¿cómo puedo cambiar el nombre de un archivo en Linux ". Use Google.
Respuesta
Usando Perl:
perl -lane "$,=" ";pop(@F);print(@F)" in
Usando rev
+ cut
:
rev in | cut -d " " -f 2- | rev
Respuesta
Usando GNU sed:
sed -r "s/\s+\S+$//" input.txt
En general, este funciona con BSD sed en OSX, así como con GNU sed:
sed "s/[[:space:]]\{1,\}[^[:space:]]\{1,\}$//" input.txt
Respuesta
Si el delimitador es siempre un solo carácter (por lo que dos o más delimitadores consecutivos designan campos vacíos), podría head
solo la primera línea de su archivo de entrada, cuente los delimitadores ( n
delimitadores significa que la cantidad de campos es n+1
) luego use cut
para imprimir desde el 1
st campo hasta el n
th campo (penúltimo), p. ej. con entrada delimitada por tabuladores:
n=$(head -n 1 infile | tr -dc \\t | tr \\t \\n | wc -l) cut -f1-$n infile > outfile
o p. ej.con un archivo csv :
n=$(head -n 1 infile | tr -dc , | tr , \\n | wc -l) cut -d, -f1-$n infile > outfile
Ejecutaré algunos puntos de referencia más tarde si tengo tiempo, pero con una entrada enorme, creo que esto La solución debería ser más rápida que otras soluciones que usan expresiones regulares, ya que esta realiza un procesamiento mínimo en la primera línea para obtener el número de campos y luego usa cut
que está optimizado para este trabajo.
Respuesta
Portabilidad, puede usar cualquiera de estos:
sed "s/[[:space:]]*[^[:space:]]*$//" file awk "{sub(/[[:space:]]*[^[:space:]]*$/,"")}1" file
Respuesta
Usando vim:
Abrir archivo en vim
vim <filename>
Vaya a la primera fila, en caso de que el cursor se coloque en cualquier otro lugar.
gg
Cree una macro llamada «q» qq
, que va al final de la línea actual $
, luego vuelve al último espacio F
(F mayúscula, seguida de ESPACIO literal) luego borre desde la posición actual hasta el final de la línea D
vaya a la siguiente línea j
y detenga la grabación de macros con q
.
qq$F Djq
Ahora podemos repetir nuestra macro con @q
para cada línea.
También podemos presionar @@
para repetir la última macro o incluso más fácil:
99@q
para repetir la macro 99 veces.
Nota: El número no debe coincidir exactamente con las líneas.
Respuesta
Para personas que tienen un problema similar pero con diferentes separadores de campo, este awk
conservará el separador de campo correctamente:
$ cat file foo.bar.baz baz.bar.foo $ awk -F"." "sub(FS $NF,x)" file foo.bar baz.bar
cut
suena como la herramienta para el trabajo.