'cut': selecionando colunas contendo uma string

3

Eu tenho um arquivo grande com várias colunas em cada linha. Estou familiarizado com o uso de cut -f -d para selecionar colunas específicas pelo seu número.

Eu verifiquei o manual de cut e não parece que haja uma maneira de regexar colunas de correspondência.

O que eu quero fazer especificamente é:

  • selecione a segunda coluna de cada linha
  • e também selecione todas as colunas que contêm a string "hello" (pode não haver nenhuma, se não pode ser qualquer coluna (s) e não a mesma coluna (s) para cada linha)

Quais são as ferramentas de terminal mais convenientes para esta operação?

EDITAR:

Exemplo simplificado

x ID23 a b c hello1
x ID47 hello2 a b c
x ID49 hello3 a b hello4
x ID53 a b c d

O resultado que eu quero é:

ID23 hello1
ID47 hello2
ID49 hello3 hello4

ou alternativamente:

ID23 hello1
ID47 hello2
ID49 hello3 hello4
ID53

Para elaborar o exemplo dado:

  • As colunas são definidas por um espaço
  • se ou não "imprimir apenas se a string estiver presente" não é realmente importante, posso apenas grep para "olá" se necessário
  • podemos supor que a string "hello" nunca estará na coluna 1 ou 2.
por Juicy 30.06.2016 / 09:51

2 respostas

6

Se um espaço no final da linha não te atrapalhar muito:

$ awk '{for(i=1;i<=NF;i++) if(i==2 || $i~"hello") printf $i" ";print ""}' file

ID23 hello1 
ID47 hello2 
ID49 hello3 hello4 
ID53 

Isso não pressupõe nada sobre a posição da string "hello".

    
por 30.06.2016 / 10:35
4

Eu não acho que isso será possível usando ferramentas simples como cut . Ou, pelo menos, não facilmente. Aqui está uma solução Perl:

$ perl -lane '$k=join " ",grep{/hello/}@F; print "$F[1] $k" if $k' file 
ID23 hello1
ID47 hello2
ID49 hello3 hello4

Que você poderia simplificar usando grep primeiro:

$ grep hello file | perl -lane 'print "$F[1] ", join(" ", grep{/hello/}@F)'
ID23 hello1
ID47 hello2
ID49 hello3 hello4

Explicação

A opção -n informa perl para ler sua entrada linha por linha e aplicar o script fornecido por -e . O sinalizador -l adiciona uma nova linha ( \n ) a cada print chamada. A opção -a faz com que perl divida suas linhas de entrada no espaço em branco na matriz @F .

Portanto, o próprio script está procurando todos os elementos de @F (todas as colunas) que correspondem a hello e salvando-os como a string separada por espaço $k ( $k=join " ",grep{/hello/}@F; ). Em seguida, o segundo campo ( $F[1] ) e $k serão impressos se $k for definido, se pelo menos um hello for encontrado.

A segunda versão é a mesma, exceto que não precisamos de $k e imprimir diretamente, pois sabemos que pelo menos um hello estará sempre presente.

    
por 30.06.2016 / 10:43