¿Cómo imprimir la tercera columna a la última columna?

121

Estoy tratando de eliminar las dos primeras columnas (de las cuales no estoy interesado) de un archivo de registro DbgView. Parece que no puedo encontrar un ejemplo que se imprima desde la columna 3 en adelante hasta el final de la línea. Tenga en cuenta que cada línea tiene un número variable de columnas.

Amit G
fuente
posible duplicado de Usar awk para imprimir todas las columnas desde la enésima hasta la última
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

108

... o una solución más simple: cut -f 3- INPUTFILE simplemente agregue el delimitador correcto (-d) y obtendrá el mismo efecto.

Marcin
fuente
9
Tenga en cuenta que esto solo funciona si el delimitador es exactamente el mismo entre todas las columnas ... Por ejemplo, no puede usar cortar con un delimitador como \ d +. (Que yo sepa)
Zach Wily
72
Cuando la pregunta se titula awk, no es apropiado aceptar una respuesta que no sea awk. ¿Qué pasa si la gente lo necesita para los scripts awk? Esta respuesta debería haber sido solo un comentario.
syaz
24
@SyaZ: Normalmente estaría de acuerdo, pero con la cantidad de 'awk gratuito' que hay en este tablero, pensé que era necesario mostrar una forma alternativa de realizar la tarea. ¿No estarías agradecido si alguien te mostrara una forma más sencilla y rápida de hacer la misma tarea? ¿Quizás el cartel pensó que awk es la única forma de hacer esto debido a la cantidad de respuestas "no incorrectas, pero ciertamente mejorables" a otras preguntas?
Marcin
12
Para eso es el comentario. Acepte la mejor respuesta awk y proporcione mejores sugerencias no awk sobre los comentarios. Si la gente comienza a publicar respuestas que no responden exactamente a las preguntas, será molesto al buscar (en mi caso).
syaz
12
No solo el delimitador debe ser el mismo entre todas las columnas, sino que debe haber EXACTAMENTE UN carácter delimitador entre las columnas. Entonces, si está tratando con programas que alinean su salida con delimitadores, es mejor usar awk.
sknaumov
112
awk '{for(i=3;i<=NF;++i)print $i}' 
Jonathan Feinberg
fuente
3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' sea más compacto. :)
user172818
1
Gracias, lh3. Solo estaba copiando y pegando para el manual de Gawk. :)
Jonathan Feinberg
23
esto falla con varias líneas, cada columna se registra como una nueva línea cuando se imprime con impresión
meso_2600
13
Para abordar el problema de la salida dividida, propongo esta solución: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfno imprimirá el carácter de nueva línea, mientras print ""que agregará una nueva línea después de que se hayan impreso los otros campos)
lauhub
1
O: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', lo que da: 3 4 5 6 7 8 9 10.
x-yuri
106
awk '{ print substr($0, index($0,$3)) }'

solución encontrada aquí:
http://www.linuxquestions.org/questions/linux-newbie-8/awk-print-field-to-end-and-character-count-179078/

daisaa
fuente
23
Llego un poco tarde para esto, pero esto no funcionará para registros en los que el primer o segundo campo es igual al tercero (por ejemplo, 3 2 3 4 5)
aleph_null
también es posible imprimir un rango interno: `` `# de $ 3 (incluido) a $ 6 (excluido); echo "1,2,3,4,5,6,7,8,9" | awk 'BEGIN {FS = ","; OFS = ","} {print substr ($ 0, index ($ 0, $ 3), length ($ 0) -index ($ 0, $ 6) -1)}'; # da 3,4,5
splaisan
34

La respuesta de Jonathan Feinberg imprime cada campo en una línea separada. Puede usar printfpara reconstruir el registro para la salida en la misma línea, pero también puede mover los campos un salto hacia la izquierda.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile
Pausado hasta nuevo aviso.
fuente
1
Tenga en cuenta que esto solo funciona para Gnu awk, NFPOSIX no permite la disminución .
kvantour
1
@kvantour: funciona en gawk, mawk, MacOS awk (nawk?). POSIX parece guardar silencio sobre si NFse puede reducir.
Pausado hasta nuevo aviso.
Es uno de estos divertidos rincones oscuros de awk .
kvantour
19
awk '{$1=$2=$3=""}1' file

NB: este método dejará "espacios en blanco" en los campos 1, 2, 3, pero no es un problema si solo desea ver la salida.

ghostdog74
fuente
Siga ese comando con `| sed s / ^ \ * // | column -t` para eliminar los espacios iniciales y alinear las columnas restantes
MSpreij
¿Qué significa el último 1? ¿Con qué palabra clave debo buscar awk?
Itachi
@Itachi vea el ejemplo 1 de catonmat.net/blog/awk-one-liners-explained-part-one
kvantour
1
@Nathan, resuelve este problema como{$1=$2=$3="";$0=$0;$1=$1}1
kvantour
11

Si desea imprimir las columnas después de la tercera, por ejemplo, en la misma línea, puede usar:

awk '{for(i=3; i<=NF; ++i) printf "%s ", $i; print ""}'

Por ejemplo:

Mar 09:39 20180301_123131.jpg
Mar 13:28 20180301_124304.jpg
Mar 13:35 20180301_124358.jpg
Feb 09:45 Cisco_WebEx_Add-On.dmg
Feb 12:49 Docker.dmg
Feb 09:04 Grammarly.dmg
Feb 09:20 Payslip 10459 %2828-02-2018%29.pdf

Se imprimirá:

20180301_123131.jpg
20180301_124304.jpg
20180301_124358.jpg
Cisco_WebEx_Add-On.dmg
Docker.dmg
Grammarly.dmg
Payslip 10459 %2828-02-2018%29.pdf

Como podemos ver, la nómina incluso con espacio, se muestra en la línea correcta.

Hermano
fuente
Rápido y elegante. Gracias;)
9nz9
Esto es excelente, excepto que tengo un problema con la exclusión de $ NF. Cuando establezco la condición (<= NF) obtengo el último campo, pero el primer carácter del primer campo se corta. ¿Estoy entendiendo mal algo en términos de funcionalidad?
Ken Ingram
Parece que mi problema es que ^ M está pegado al final de la última columna. No veo cómo eliminarlo.
Ken Ingram
8

¿Qué pasa con la siguiente línea:

awk '{$ 1 = $ 2 = $ 3 = ""; Imprimir archivo

Basado en la sugerencia de @ ghostdog74. El mío debería comportarse mejor cuando filtra líneas, es decir:

awk '/ ^ exim4-config / {$ 1 = ""; Imprimir archivo
Wawrzek
fuente
Corto y sencillo. También podría canalizar y agregar sed 's/\s\+//g'al final del comando para recortar los espacios
iniciales
8
awk -v m="\x0a" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

Esto corta lo que está antes del campo dado nr., N, e imprime todo el resto de la línea, incluido el campo nr.N y manteniendo el espaciado original (no se reformatea). No importa si la cadena del campo aparece también en algún otro lugar de la línea, que es el problema con la respuesta de daisaa.

Defina una función:

fromField () { 
awk -v m="\x0a" -v N="$1" '{$N=m$N; print substr($0,index($0,m)+1)}'
}

Y utilícelo así:

$ echo "  bat   bi       iru   lau bost   " | fromField 3
iru   lau bost   
$ echo "  bat   bi       iru   lau bost   " | fromField 2
bi       iru   lau bost 

La salida mantiene todo, incluidos los espacios finales

Funciona bien para archivos donde '/ n' es el separador de registros, por lo que no tiene ese carácter de nueva línea dentro de las líneas. Si desea usarlo con otros separadores de registros, use:

awk -v m="\x01" -v N="3" '{$N=m$N ;print substr($0, index($0,m)+1)}'

por ejemplo. Funciona bien con casi todos los archivos siempre que no utilicen el número char hexadecimal. 1 dentro de las líneas.

Robert Vila
fuente
4

El siguiente comando awk imprime los últimos N campos de cada línea y al final de la línea imprime un carácter de nueva línea:

awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'

Encuentre a continuación un ejemplo que enumera el contenido del directorio / usr / bin y luego contiene las últimas 3 líneas y luego imprime las últimas 4 columnas de cada línea usando awk:

$ ls -ltr /usr/bin/ | tail -3
-rwxr-xr-x 1 root root       14736 Jan 14  2014 bcomps
-rwxr-xr-x 1 root root       10480 Jan 14  2014 acyclic
-rwxr-xr-x 1 root root    35868448 May 22  2014 skype

$ ls -ltr /usr/bin/ | tail -3 | awk '{for( i=6; i<=NF; i++ ){printf( "%s ", $i )}; printf( "\n"); }'
Jan 14 2014 bcomps 
Jan 14 2014 acyclic 
May 22 2014 skype
canguelo
fuente
4
awk '{a=match($0, $3); print substr($0,a)}'

Primero encuentra la posición del inicio de la tercera columna. Con substr imprimirá la línea completa ($ 0) comenzando en la posición (en este caso a) hasta el final de la línea.

Mitchjol
fuente
3

Bueno, puedes lograr fácilmente el mismo efecto usando una expresión regular. Suponiendo que el separador es un espacio, se vería así:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'
Eddie Sullivan
fuente
1
Evitaría las expresiones regulares. Probablemente sea más lento y más fácil estropear accidentalmente.
Cascabel
1
Lo acorta así: lo awk '{ sub(/([^ ]+ +){2}/, ""); print }'que quita el patrón dos veces.
erik
3
awk '{print ""}{for(i=3;i<=NF;++i)printf $i" "}'
luigi9876
fuente
2

Solución Perl:

perl -lane 'splice @F,0,2; print join " ",@F' file

Se utilizan estas opciones de línea de comandos:

  • -n bucle alrededor de cada línea del archivo de entrada, no imprima automáticamente cada línea

  • -l elimina las nuevas líneas antes del procesamiento y las vuelve a agregar después

  • -amodo autosplit: divide las líneas de entrada en la matriz @F. Predeterminado para dividir en espacios en blanco

  • -e ejecutar el código perl

splice @F,0,2 elimina limpiamente las columnas 0 y 1 de la matriz @F

join " ",@F une los elementos de la matriz @F, usando un espacio entre cada elemento

Si su archivo de entrada está delimitado por comas, en lugar de por espacios, utilice -F, -lane


Solución de Python:

python -c "import sys;[sys.stdout.write(' '.join(line.split()[2:]) + '\n') for line in sys.stdin]" < file

Chris Koknat
fuente
1

Un poco tarde aquí, pero nada de lo anterior pareció funcionar. Intente esto, usando printf, inserta espacios entre cada uno. Elegí no tener una nueva línea al final.

awk '{for(i=3;i<=NF;++i) printf("%s ",  $i) }'
Ross
fuente
1
awk '{for (i=4; i<=NF; i++)printf("%c", $i); printf("\n");}'

imprime registros desde el cuarto campo hasta el último campo en el mismo orden en que estaban en el archivo original

Massimo
fuente
lo siento, esta no fue la respuesta correcta. es demasiado específico, pero no sé cómo eliminarlo
Massimo
1

En Bash puede usar la siguiente sintaxis con parámetros posicionales:

while read -a cols; do echo ${cols[@]:2}; done < file.txt

Más información: Manejo de parámetros posicionales en Bash Hackers Wiki

Kenorb
fuente
0

Si solo se trata de ignorar los dos primeros campos y si no desea un espacio al enmascarar esos campos (como lo hacen algunas de las respuestas anteriores):

awk '{gsub($1" "$2" ",""); print;}' file
champost
fuente
0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

Se limpian las dos primeras columnas, se sedeliminan los espacios iniciales.

sjas
fuente
-2

En AWK, las columnas se llaman campos, por lo tanto, NF es la clave

todas las filas:

awk -F '<column separator>' '{print $(NF-2)}' <filename>

solo primera fila:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
angelo.mastro
fuente