Extraindo linhas de um arquivo baseado no prefixo

1

Eu preciso extrair todas as linhas do arquivo2 que começam com um prefixo id # contido no arquivo1.

O arquivo 1 é uma coluna única como:

324
399
408
135236
321590

O arquivo 2 é de várias colunas, como:

1 [tab] 108 [tab] Anarchist [tab] 103985
...
324 [tab] 309 [tab] Melodies [tab] 230498

Qual é a maneira mais fácil e rápida de extrair apenas essas linhas do Arquivo2?

    
por Poe 23.10.2011 / 01:04

5 respostas

1
$ while read p; do awk '$1 == "'$p'"' file2; done < file1

ou:

$ awk -F'\t' 'FNR==NR { a[$0]; next } $1 in a' file1 file2
  • FNR : o número de registros lidos a partir do arquivo atual processado
  • NR : número total de registros de entrada
  • FNR==NR : só é verdade quando awk está lendo o file1
  • a[$0] : cria um elemento de matriz indexado por $0 (de file1 )
  • $1 in a : verifica se cada linha sendo lida de file2 existe como um índice na matriz a
por 23.10.2011 / 01:19
1

código bash para fazer isso:

for i in $(cat file1); do egrep "^$i\s" file2; done
    
por 23.10.2011 / 01:39
1

Este é provavelmente o mais rápido:

grep -f <( sed 's/.*/^&\t/' file1) file2

As respostas usando for e while loops serão muito lentas.

A resposta awk dos quanta deve funcionar. Eu não sei por que isso não aconteceria, a menos que suas terminações de linha não sejam Unix ou que file1 seja muito grande.

    
por 23.10.2011 / 02:45
0

1) Podemos usar alguma lógica OR do grep. Por exemplo

$> grep -P "^(324|399|408|135236|321590).*" file2
324 [tab] 309 [tab] Melodies [tab] 230498

Então, a questão é: como podemos obter essa variável para o grep?

2) Podemos ecoar o arquivo1 em uma única linha e substituir os delimitadores por | , em vez de adicionar colchetes.

$> echo 'cat file1' | sed -r -e 's/([0-9])\ ([0-9])/,/g'
324,399,408,135236,321590

Então, finalmente, temos uma variante sem loops for-while.

grep -P "^($( echo 'cat file1' | sed -r -e 's/([0-9])\ ([0-9])/|/g'  )).*" file2
    
por 23.10.2011 / 02:20
0

O comando join comanda o servidor GNU coreutils exatamente com este propósito, mas é exigente quanto à sua entrada.

$ sort file1 > sorted1
$ sort file2 > sorted2
$ join -t"      " sorted1 sorted2 | sort -n

O comando join requer que seus arquivos de entrada sejam classificados lexicograficamente, não numericamente. Assim, toda essa classificação das entradas e da saída.

Para especificar que a saída de join deve ser delimitada por tabulações, use -t" caractere de tabulação " , que você digitaria como Ctrl-V Tab no prompt Bash.

    
por 23.10.2011 / 09:45

Tags