Como eu seleciono eficientemente números de linha específicos de uma lista de registros?

3

Eu quero ter uma lista de números representando números de linha de um arquivo de origem que eu quero filtrar e filtrar essas linhas do arquivo de origem. Como posso construir um pipeline unix para extrair essas linhas do arquivo de origem?

O pipeline pode se parecer com:

cat sourcefile.tsv | some-filter linenumbers.txt  > extractedrecords.tsv

Eu não consigo pensar em uma combinação de ferramentas unix para fazer isso fora do topo da minha cabeça. O substituto é escrever um script bash que use sed -n [number]p sourcefile.tsv para cada número em linenumbers.txt.

Se meu plano de fallback for razoavelmente eficiente em comparação com as alternativas, por favor me avise também.

    
por dan 09.12.2014 / 20:26

2 respostas

2

Supondo que linenumbers.txt tenha um número por linha

awk 'NR == FNR{a[$0]; next};FNR in a' linenumbers.txt sourcefile.csv > extractedrecords.tsv

Pode fazer o trabalho.

Ou com bash

join  -t':' -o2.1,2.2  <(sort linenumbers.txt) <(awk '{print NR":"$0}' \
sourcefile.csv | sort -k1,1 -t':')  | sort -k1,1n -t':' | cut -f2- -d':'

Todos os arcos adicionais são necessários porque join não suporta arquivos de entrada numericamente classificados

    
por 09.12.2014 / 21:18
2

Você está no caminho certo com o sed: tudo o que você precisa fazer é transformar sua lista de números de linha a ser seguida por p e newline e usar isso como um script sed. Por exemplo, se você tiver uma lista separada por espaços:

lines="2 3 5 7 11 13"
<sourcefile.tsv sed -n "$(echo "$lines" | sed 's/$/p/; s/ /p\n/')"  >extractedrecords.tsv

Awk é outra possibilidade.

lines="2 3 5 7 11 13"
export lines
<sourcefile.tsv awk '" "ENVIRON["lines"]" " ~ " "NR" "' >extractedrecords.tsv
    
por 10.12.2014 / 01:16