¿Cómo imprimir todas las columnas después de un número en particular usando awk?

Respuestas:

82
awk '{ s = ""; for (i = 9; i <= NF; i++) s = s $i " "; print s }'
Amadan
fuente
3
un par de ligeros refinamientos:awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'
Glenn Jackman
Gracias @glenn, de hecho es un poco más general. De todos modos, definitivamente estoy de acuerdo en que sería mejor usar cuto perlpara esto. Use esto solo si realmente insiste en tenerlo awk.
Amadan
1
@SiegeX: No agrega bytes NUL, deja el FS en su lugar entre cada campo vacío.
Pausado hasta nuevo aviso.
1
Consulte la respuesta de @ Ascherer sobre elegancia.
3
@veryhungrymike: La elegancia es agradable, pero prefiero estar en lo correcto. : p
Amadan
68

Cuando desea hacer una variedad de campos, awkrealmente no tiene una forma sencilla de hacerlo. En su cutlugar recomendaría :

cut -d' ' -f 9- ./infile

Editar

Se agregó un delimitador de campo de espacio debido a que el valor predeterminado es una pestaña. Gracias a Glenn por señalar esto.

SiegeX
fuente
15
Una cosa acerca de cut es que usa un delimitador específico (tabulador por defecto), donde awk usa "espacios en blanco". Con corte, 2 pestañas consecutivas delimitan un campo vacío.
Glenn Jackman
1
Como señaló @glennjackman, el delimitador de awk es "espacio en blanco" (también cualquier cantidad). Por lo tanto, establecer el delimitador de corte en un solo espacio no coincidiría con el comportamiento también. desafortunadamente, el bucle es lo mejor que se puede hacer, por lo que parece.
poncha
Éste no funciona correctamente. Prueba el comando find . | xargs ls -l | cut -d' ' -f 9-. Por alguna razón, los espacios dobles también se cuentan. Ejemplo: lrwxrwxrwx 1 me me 21 Dec 12 00:00 ./file_a lrwxrwxrwx 1 me me 64 Dec 6 00:06 ./file_bresultará en./file_a 00:06 ./file_b
Marco Pashkov
@MarcoPashkov, por favor, explique sobre Este no funciona correctamente , especialmente considerando que usa exactamente el mismo código en su canalización. Por cierto, nunca
SiegeX
cortar no hace el trabajo aquí. Por ejemplo, si su entrada es "foo bar" (espacio simple) para una línea, y "foo ___ bar" (es decir, varios espacios, pero SO es demasiado inteligente para mostrarlo) para otra, cut los procesará de manera diferente.
UKMonkey
54
awk '{print substr($0, index($0,$9))}'

Editar : Tenga en cuenta que esto no funciona si algún campo antes del noveno contiene el mismo valor que el noveno.

Ascherer
fuente
3
este es brillante!
10
@veryhungrymike: ... y no funciona si algún campo antes del noveno contiene el mismo valor que el noveno.
Amadan
6
Probablemente debido a la frase clásica "es de esperar que su archivo no tenga ese problema". Es un absoluto no-no en la ingeniería de software el decir: "No vamos a perder el tiempo incluyendo la comprobación de errores para la entrada de, por ejemplo, valores negativos, porque" esperamos que el usuario sea lo suficientemente inteligente como para no probarlos ". estrellarse nuestra herramienta '". ¡JAJAJA! ¡Siempre me encanta escuchar esto! (Me gusta un buen sentido del humor) Bueno, como idiotas hacen existir, es deber de los desarrolladores para hacer sus cosas a prueba de idiotas ! En lugar de "esperar el bien del hombre". Eso es más bien una actitud de esperar con los filósofos, no s / w ingenieros ... LOL
SyntaxError
3
No estaba diciendo que no verificara los errores, pero si sabe que no se encontrará con el problema, entonces esta solución está bien, como dije. Pero gracias por el innecesario voto negativo @syntaxerror. Esta solución funcionará para algunos, como mostrarán los 19 votos a favor (actualmente), pero si no es así, no la use para su solución. Hay muchas formas de resolver el problema del OP.
Ascherer
1
Si está utilizando awk en la línea de comandos en su trabajo diario, esta es definitivamente la solución que desea. ¿No es obvio? La comprobación de errores, etc., realmente no importa en ese caso, ya que lo está escribiendo y puede detectar este tipo de cosas antes de presionar enter (personalmente, no creo que awk deba usarse para nada más de todos modos, es por eso que ¡Tengo perl, python, tcl y más de 100 lenguajes de scripting mejores, más rápidos y menos molestos! '' Por supuesto, tal vez les estoy dando demasiado crédito a mis compañeros desarrolladores de software y realmente necesitan verificar los errores incluso en lo que escriben sobre la marcha (??)
osirisgothra
11
sed -re 's,\s+, ,g' | cut -d ' ' -f 9-

En lugar de tratar con espacios en blanco de ancho variable, reemplace todos los espacios en blanco como un solo espacio. Luego use simple cutcon los campos de interés.

No usa awk, por lo que no es pertinente, pero parecía apropiado dadas las otras respuestas / comentarios.

Algún tonto
fuente
1
Haga su respuesta más completa, de lo contrario publique esto como un comentario a la pregunta.
Alper Turan
Esto es ideal para su ps faux | uso. Nunca tenga miedo de admitir que la herramienta XYZ no es la más adecuada.
kevinf
10

Generalmente, perl reemplaza awk / sed / grep et. al., y es mucho más portátil (además de ser una mejor navaja).

perl -lane 'print "@F[8..$#F]"'

Timtowtdi se aplica, por supuesto.

bobbogo
fuente
Debe agregar la opción de línea de comando -lo agregar \na la declaración de impresión.
Glenn Jackman
@glenn jackman: Posiblemente. No es necesario si forma parte de otro mensaje, o si está asignado a una variable, etc. En lo que respecta a "mejor", Perl ciertamente se ve mejor en lo pequeño. Es cierto que puede verse muy desordenado en grande.
bobbogo
No me malinterpretes, me gusta Perl. Sin embargo, amo awk por lo que es.
Glenn Jackman
Mi dispositivo integrado no viene con Perl, pero tiene awk.
Sepero
Votación negativa porque la pregunta era cómo hacer esto en awk, no en perl, ruby, java, python, bash.
Tom Harrison
3
awk -v m="\x01" -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 Ascherer.

Defina una función:

fromField () { 
awk -v m="\x01" -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. Para N = 0, devuelve la línea completa, tal cual, y para n> NF la cadena vacía

Robert Vila
fuente
Esta es una buena idea. No funciona del todo en una Mac actual con el típico gawk, porque $ 0 colapsa. La solución es establecer una variable en $ 0 como primer paso, como: '{s = $ 0; ... imprimir substr (s, index (s, m) +1}
joelparkerhenderson
1

Aquí hay un ejemplo de ls -lsalida:

-rwxr-----@ 1 ricky.john  1493847943   5610048 Apr 16 14:09 00-Welcome.mp4
-rwxr-----@ 1 ricky.john  1493847943  27862521 Apr 16 14:09 01-Hello World.mp4
-rwxr-----@ 1 ricky.john  1493847943  21262056 Apr 16 14:09 02-Typical Go Directory Structure.mp4
-rwxr-----@ 1 ricky.john  1493847943  10627144 Apr 16 14:09 03-Where to Get Help.mp4

Mi solución para imprimir cualquier publicación $9esawk '{print substr($0, 61, 50)}'

Rickydj
fuente
0
ruby -lane 'print $F[3..-1].join(" ")' file
Kurumi
fuente
0

Para mostrar los primeros 3 campos e imprimir los campos restantes, puede usar:

awk '{s = ""; for (i=4; i<= NF; i++) s= s $i : "; print $1 $2 $3 s}' filename

donde $ 1 $ 2 $ 3 son los primeros 3 campos.

Raymond C Borges Hink
fuente
0
function print_fields(field_num1, field_num2){
    input_line = $0

    j = 1;
    for (i=field_num1; i <= field_num2; i++){
        $(j++) = $(i);

    }
    NF = field_num2 - field_num1 + 1;
    print $0

    $0 = input_line
}
msol01
fuente
0

Usar cortar en lugar de awk y superar los problemas de averiguar en qué columna comenzar mediante el comando -c de corte de caracteres.

Aquí estoy diciendo, dame todos menos los primeros 49 caracteres de la salida.

 ls -l /some/path/*/* | cut -c 50-

Al /*/*/final del comando ls dice muéstrame lo que hay en los subdirectorios también.

También puede extraer ciertos rangos de caracteres ala (de la página de manual de corte). Por ejemplo, muestre los nombres y las horas de inicio de sesión de los usuarios que han iniciado sesión actualmente:

       who | cut -c 1-16,26-38
Joe
fuente