Como imprimir a terceira coluna na última coluna?


121

Estou tentando remover as duas primeiras colunas (nas quais não estou interessado) de um arquivo de log DbgView. Não consigo encontrar um exemplo que imprima da coluna 3 em diante até o final da linha. Observe que cada linha possui um número variável de colunas.


Respostas:


108

... ou uma solução mais simples: cut -f 3- INPUTFILE basta adicionar o delimitador correto (-d) e você terá o mesmo efeito.


9
Observe que isso só funciona se o delimitador for exatamente o mesmo entre todas as colunas ... Por exemplo, você não pode usar recortar com um delimitador como \ d +. (Que eu saiba.)
Zach Wily

72
Quando a pergunta é intitulada awk, é inapropriado aceitar uma resposta diferente de awk. E se as pessoas precisarem dele para scripts awk? Essa resposta deveria ser apenas um comentário.
syaz 01 de

24
@SyaZ: Normalmente eu concordaria, mas com a quantidade de 'awk gratuito' acontecendo neste fórum, achei que fosse necessário mostrar uma maneira alternativa de fazer a tarefa. Você não ficaria grato se alguém lhe mostrasse uma maneira mais simples e rápida de fazer a mesma tarefa? Talvez o autor do cartaz tenha pensado que awk é a única maneira de fazer isso por causa do número de respostas 'não incorretas, mas certamente improváveis ​​após' a outras perguntas?
Marcin

12
É para isso que serve o comentário. Aceite a melhor resposta do awk e forneça melhores sugestões de não awk nos comentários. Se as pessoas começarem a postar respostas que não respondem exatamente às perguntas, será irritante ao pesquisar (no meu caso).
syaz

12
Não apenas o delimitador deve ser o mesmo entre todas as colunas, mas deve haver EXATAMENTE UM caractere delimitador entre as colunas. Portanto, se você estiver lidando com programas que alinham sua saída com delimitadores, é melhor usar o awk.
sknaumov de

112
awk '{for(i=3;i<=NF;++i)print $i}' 

3
awk '{for (i = 3; i <= NF; ++ i) print $ i}' seja mais compacto. :)
user172818

1
Obrigado, lh3. Eu estava apenas copiando e colando para o manual do gawk. :)
Jonathan Feinberg

23
isso falha com várias linhas, cada coluna é tratada como uma nova linha quando impressa na impressão
meso_2600

13
Para resolver o problema de saída dividida, proponho esta solução: awk '{for(i=3;i<=NF;++i)printf $i""FS ; print ""}'( printfnão imprimirá o caractere de nova linha, mas print ""adicionarei a nova linha depois que os outros campos forem impressos)
lauhub

1
Ou: echo $(seq 1 10) | awk '{for (i=3; i<=NF; i++) printf $i FS}', o que dá: 3 4 5 6 7 8 9 10.
x-yuri

106
awk '{ print substr($0, index($0,$3)) }'

solução encontrada aqui:
http://www.linuxquestions.org/questions/linux-newbie-8/awk-print-field-to-end-and-character-count-179078/


23
Estou meio atrasado para isso, mas isso não funcionará para registros em que o primeiro ou o segundo campo é igual ao terceiro (por exemplo, 3 2 3 4 5)
aleph_null

imprimir um intervalo interno também é possível: `` `# de $ 3 (incluído) a $ 6 (excluído); 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)}'; # dá 3,4,5```
splaisan

34

A resposta de Jonathan Feinberg imprime cada campo em uma linha separada. Você pode usar printfpara reconstruir o registro para saída na mesma linha, mas também pode simplesmente mover os campos um salto para a esquerda.

awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}' logfile

1
Esteja ciente de que isso só funciona para Gnu awk, decrementar NFnão é permitido pelo POSIX.
kvantour

1
@kvantour: Funciona em gawk, mawk, MacOS awk (nawk?). POSIX parece não saber se NFpode ser diminuído.
Pausado até novo aviso.

É um desses cantos escuros engraçados do awk .
kvantour

19
awk '{$1=$2=$3=""}1' file

NB: este método deixará "espaços em branco" em 1,2,3 campos, mas não é um problema se você quiser apenas olhar a saída.


Execute esse comando com `| sed s / ^ \ * // | coluna -t` para retirar os espaços iniciais e alinhar as colunas restantes
MSpreij

O que significa o último 1? com qual palavra-chave devo pesquisar awk?
Itachi


1
@Nathan você resolve este problema como{$1=$2=$3="";$0=$0;$1=$1}1
kvantour

11

Se você quiser imprimir as colunas após o terceiro, por exemplo, na mesma linha, você pode usar:

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

Por exemplo:

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

Vai 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, o holerite mesmo com espaço, aparece na linha correta.


Rápido e elegante. Obrigado;)
9nz9 de

Isso é excelente, exceto que tenho um problema com a exclusão de $ NF. Quando defino a condição (<= NF), obtenho o último campo, mas o primeiro caractere do primeiro campo é cortado. Estou entendendo mal em termos de funcionalidade?
Ken Ingram

Parece que meu problema é que ^ M está preso no final da última coluna. Não vejo como removê-lo.
Ken Ingram

8

Que tal a seguinte linha:

awk '{$ 1 = $ 2 = $ 3 = ""; imprimir arquivo

Com base na sugestão de @ ghostdog74. O meu deve se comportar melhor quando você filtra linhas, ou seja:

awk '/ ^ exim4-config / {$ 1 = ""; imprimir arquivo

Curto e simples. Também pode canalizar e adicionar sed 's/\s\+//g'no final do comando para cortar espaços à esquerda
jumping_monkey

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

Isso corta o que está antes do campo especificado nr., N, e imprime todo o resto da linha, incluindo o campo nr.N e mantém o espaçamento original (não reformata). Não importa se a string do campo aparece também em algum outro lugar da linha, que é o problema com a resposta de daisaa.

Defina uma função:

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

E use-o assim:

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

A saída mantém tudo, incluindo espaços à direita

Funciona bem para arquivos onde '/ n' é o separador de registro, então você não tem aquele caractere de nova linha dentro das linhas. Se você quiser usá-lo com outros separadores de registro, use:

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

por exemplo. Funciona bem com quase todos os arquivos, desde que não usem hexadecimal char nr. 1 dentro das linhas.


4

O seguinte comando awk imprime os últimos N campos de cada linha e no final da linha imprime um novo caractere de linha:

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

Encontre abaixo um exemplo que lista o conteúdo do diretório / usr / bin e, em seguida, contém as últimas 3 linhas e, em seguida, imprime as últimas 4 colunas de cada linha 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

4
awk '{a=match($0, $3); print substr($0,a)}'

Primeiro você encontra a posição do início da terceira coluna. Com substr você imprimirá toda a linha ($ 0) começando na posição (neste caso a) até o final da linha.


3

Bem, você pode obter facilmente o mesmo efeito usando uma expressão regular. Presumindo que o separador seja um espaço, seria semelhante a:

awk '{ sub(/[^ ]+ +[^ ]+ +/, ""); print }'

1
Eu evitaria regex. Provavelmente é mais lento e fácil de bagunçar acidentalmente.
Cascabel

1
É encurtado assim: o awk '{ sub(/([^ ]+ +){2}/, ""); print }'que tira o padrão duas vezes.
erik


2

Solução Perl:

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

Estas opções de linha de comando são usadas:

  • -n faça um loop em cada linha do arquivo de entrada, não imprima automaticamente todas as linhas

  • -l remove novas linhas antes do processamento e as adiciona de volta depois

  • -amodo autosplit - divide as linhas de entrada no array @F. O padrão é divisão em espaços em branco

  • -e execute o código perl

splice @F,0,2 remove claramente as colunas 0 e 1 da matriz @F

join " ",@F junta os elementos da matriz @F, usando um espaço entre cada elemento

Se o seu arquivo de entrada for delimitado por vírgulas, em vez de delimitado por espaço, use -F, -lane


Solução Python:

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


1

Um pouco tarde aqui, mas nenhuma das opções acima pareceu funcionar. Tente isso, usando printf, insere espaços entre cada um. Eu escolhi não ter nova linha no final.

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

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

imprime registros começando do 4º campo ao último campo na mesma ordem em que estavam no arquivo original


desculpe, esta não era uma resposta totalmente correta. é muito específico, mas não sei como excluí-lo
Massimo


0

Se for apenas para ignorar os dois primeiros campos e se você não quiser um espaço ao mascarar esses campos (como algumas das respostas acima fazem):

awk '{gsub($1" "$2" ",""); print;}' file

0
awk '{$1=$2=""}1' FILENAME | sed 's/\s\+//g'

As duas primeiras colunas são apagadas, sedremove os espaços iniciais.


-2

Em AWK, as colunas são chamadas de campos, portanto, NF é a chave

todas as linhas:

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

apenas primeira linha:

awk -F '<column separator>' 'NR<=1{print $(NF-2)}' <filename>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.