Feito isso abaixo -
awk 'FNR==NR{a[i++]=$0; max=i; next}
{if ((NR % max) == 0) {i=max-1} else {i=(NR%max) - 1};
printf "%s,%s\n",$0,a[i]}' smaller_file larger_file
Mas se alguém souber o caminho mais rápido do que isso, sugira
Eu tenho um arquivo muito grande (~ dados de 10Gb) que contém dados no formato abaixo -
'1','1'
'2','2'
'3','3'
'4','4'
'5','5'
'6','6'
'7','7'
'8','8'
'9','9'
'10','10'
e formato de outro arquivo (que tem 300Kb de tamanho) é -
1,2
1,3
1,4
1,5
1,6
1,7
1,8
1,9
1,10
2,1
2,3
2,4
2,5
2,6
2,7
2,8
2,9
saída desejada -
'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
desde que o arquivo de entrada contenha mais de 10 milhões de registros. então, fazer isso por meio de um loop será uma operação muito cara.
Feito isso abaixo -
awk 'FNR==NR{a[i++]=$0; max=i; next}
{if ((NR % max) == 0) {i=max-1} else {i=(NR%max) - 1};
printf "%s,%s\n",$0,a[i]}' smaller_file larger_file
Mas se alguém souber o caminho mais rápido do que isso, sugira
Parece que você está procurando percorrer o conteúdo do arquivo menor
com awk
awk 'NR == FNR{a[++i]=$0; next};
{print $0, a[FNR % i? FNR % i: i]}' smaller_file larger_file
e python
from itertools import cycle, izip
with open('larger_file') as f1, open('smaller_file') as f2:
z = izip(f1, cycle(f2))
for l, m in z:
print l.rstrip('\n'), m.rstrip('\n')
paste -d",''," ./file1 - ./file2 - - </dev/null >out
... dados dados de exemplo que são gravados na saída:
'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
,'2,3',
,'2,4',
,'2,5',
,'2,6',
,'2,7',
,'2,8',
,'2,9',
,'',
É um pouco difícil para eu dizer exatamente quais são os critérios para parar a saída, mas escrever uma saída idêntica à saída do seu exemplo:
{ paste -d",''," ./file1 - ./file2 - - |
sed -ne's/,/&/4p;t' -eq
} </dev/null
'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
Como muitos já apontaram, colar é a ferramenta certa aqui.
paste -d ,\'\' file1 /dev/null file2 /dev/null
Se file2
for menor que file1
, então paste
agirá como se tivesse tantas linhas vazias no final para corresponder a file2
.
Se você quiser agir como se file2
fosse repetido várias vezes, repita várias vezes até atingir a contagem de linhas de file1
.
while true; do cat file2; done | head -n "$(wc -l file1)" |
paste -d ,\'\' file1 /dev/null - /dev/null
Isso requer mais de file1
duas vezes. Dependendo da velocidade relativa de sua CPU e E / S, pode ser mais rápido evitar paste
e, em vez disso, usar uma ferramenta que pode processar vários arquivos de maneira mais flexível, como o awk. Aqui está uma solução awk que não requer o carregamento de qualquer arquivo na memória por completo (se file2
for pequeno, o cache de disco cuidará disso de qualquer maneira).
awk -v file2=file2 '
!getline s <file2 {close(file2); getline s <file2}
{print $0 ",7" s "7"}' file1
Explicação: getline s <file2
lê a próxima linha de file2
, abrindo-a se necessário. Se isso falhar (porque o final do arquivo foi atingido), feche o arquivo e inicie novamente.
Tags text-processing