Eu tenho o seguinte arquivo:
id name age
1 ed 50
2 joe 70
Quero imprimir apenas o id
e age
colunas. Agora eu apenas uso awk
:
cat file.tsv | awk '{ print $1, $3 }'
No entanto, isso requer conhecer os números das colunas. Existe uma maneira de fazer isso onde eu possa usar o nome da coluna (especificado na primeira linha), em vez do número da coluna?
cat
não é necessário, BTW. Você poderia usarawk '{ print $1, $3 }' file.tsv
id
vez de$1
e emage
vez de$3
Respostas:
Talvez algo parecido com isto:
Se você quiser especificar as colunas a serem impressas na linha de comando, faça algo assim:
(Observe a
-v
opção para obter a variável definida noBEGIN
bloco.)fonte
awk -f t.awk col1 col2 ... coln input
seria ideal;awk -f t.awk cols=col1,col2,...,coln input
iria trabalhar muitofor (i in out)
não possui ordem inerente.gawk
oferecePROCINFO["sorted_in"]
como solução, iterar sobre o índice com afor( ; ; )
é provavelmente melhor.Apenas lançando uma solução Perl no lote:
fonte
csvkit
Converta os dados de entrada em um formato csv e use uma ferramenta csv, como
csvcut
emcsvkit
:Instale o csvkit:
Use
tr
com a opção squeeze-s
para convertê-lo em um arquivo csv válido e apliquecsvcut
:Se você deseja retornar ao formato de dados antigo, pode usar
tr ',' ' ' | column -t
Notas
O csvkit também suporta delimitadores diferentes ( opção compartilhada
-d
ou--delimiter
), mas retorna um arquivo csv:Se o arquivo usar apenas espaços para separar colunas (sem guias), os trabalhos a seguir
Se o arquivo usar uma guia para separar colunas, o seguinte funciona e
csvformat
pode ser usado para recuperar o arquivo tsv:Tanto quanto eu verifiquei, apenas uma única guia é permitida.
csvlook
pode formatar a tabela em um formato de tabela de remarcaçãoUUOC (uso inútil de gato) : Eu gosto dessa maneira de construir o comando.
fonte
tr
também. Os arquivos TSV são suportados diretamente, sem a necessidade de convertê-los para CSV. A opção-t
(aka--tabs
) dizcvscut
para usar guias como delimitador de campo. E-d
ou--delimiter
para usar qualquer caractere como delimitador.-d
e-t
estão semi-quebradas. eles trabalham para especificar o delimitador de entrada, mas o delimitador de saída é codificado permanentemente para ser sempre uma vírgula. OMI quebrado - deve ser o mesmo que o delimitador de entrada ou ter outra opção para permitir que o usuário defina o delimitador de saída, comoawk
os vars FS e OFS.Se você quiser apenas se referir a esses campos por seus nomes, em vez de números, você pode usarread
:EDITAR
Eu finalmente vi o seu significado! Aqui está uma função bash que imprimirá apenas as colunas que você especificar na linha de comando (por nome ).
Veja como você pode usá-lo com o arquivo que você apresentou:
(A função lê
stdin
.< file.tsv printColumns ...
É equivalente aprintColumns ... < file.tsv
ecat file.tsv | printColumns ...
)Nota: Preste atenção aos nomes das colunas solicitadas! Esta versão carece de verificações de sanidade, portanto, coisas desagradáveis podem acontecer se um dos argumentos for algo como
"anything; rm /my/precious/file"
fonte
id
,name
eage
, não muda o fato de que a ordem é codificado em suaread
linha.time { command(s); }
).time cat temp.txt | ./col1 CHR POS > /dev/null 99.144u 38.966s 2:19.27 99.1% 0+0k 0+0io 0pf+0w time awk -f col2 c1=CHR c2=POS temp.txt > /dev/null 0.294u 0.127s 0:00.50 82.0% 0+0k 0+0io 0pf+0w
Pelo que vale a pena. Isso pode lidar com qualquer número de colunas na origem e qualquer número de colunas a serem impressas, em qualquer sequência de saída que você escolher; apenas reorganize os argumentos ...
por exemplo. ligar:
script-name id age
saída
fonte
Se o arquivo que você está lendo nunca puder ser gerado pelo usuário, você poderá abusar da leitura incorporada:
A primeira linha inteira do arquivo de entrada é substituída na lista de argumentos,
read
passando todos os nomes de campos da linha de cabeçalho como nomes de variáveis. O primeiro deles recebe o 1 queseq 100
gera, o segundo recebe o 2, o terceiro recebe o 3 e assim por diante. O excesso deseq
produção é absorvido pela variável dummyextra
. Se você souber o número de colunas de entrada com antecedência, poderá alterar os 100 para corresponder e se livrarextra
.O
awk
script é uma sequência de aspas duplas, permitindo que as variáveis de shell definidas porread
sejam substituídas no script comoawk
números de campo.fonte
Geralmente é mais fácil olhar apenas o cabeçalho do arquivo, contar o número da coluna que você precisa ( c ) e usar o Unix
cut
:Mas quando existem muitas colunas ou muitos arquivos, eu uso o seguinte truque feio:
Testado no OSX,
file.csv
é delimitado por vírgula.fonte
Aqui está uma maneira rápida de selecionar uma única coluna.
Digamos que queremos a coluna chamada "foo":
Basicamente, pegue a linha do cabeçalho, divida-a em várias linhas com um nome de coluna por linha, numere as linhas, selecione a linha com o nome desejado e recupere o número da linha associada; use esse número de linha como o número da coluna para o comando recortar.
fonte
Procurando uma solução semelhante (eu preciso da coluna denominada id, que pode ter um número variável de colunas), me deparei com esta:
fonte
Eu escrevi um script Python para esse fim que basicamente funciona assim:
Eu o chamei
hgrep
de cabeçalho grep , ele pode ser usado assim:O script inteiro é um pouco mais longo, porque ele usa
argparse
para analisar argumentos da linha de comando e o código é o seguinte:fonte
awk
, apesar de todas as suas safras, é inerentemente indexado por inteiro, como estácut
.Aqui estão várias ferramentas projetadas para manipular dados indexados por nome (a maioria deles manipula apenas CSV e TSV, que são formatos de arquivo muito populares):
fonte
Experimente este pequeno utilitário awk para cortar cabeçalhos específicos - https://github.com/rohitprajapati/toyeca-cutter
Exemplo de uso -
fonte