Como dividir um arquivo grande em duas partes, em um padrão?
Dado um exemplo file.txt
:
ABC
EFG
XYZ
HIJ
KNL
Quero dividir esse arquivo de XYZ
modo que file1
contenha linhas até o XYZ
restante das linhas file2
.
text-processing
sed
awk
split
d.putto
fonte
fonte
XYZ
linha deve ser incluída na saída ou não?Respostas:
Com
awk
você pode fazer:Explicação: O primeiro
awk
argumento (out=file1
) define uma variável com o nome do arquivo que será usado para a saída enquanto o argumento subsequente (largefile
) for processado. Oawk
programa imprimirá todas as linhas no arquivo especificado pela variávelout
({print >out}
). Se o padrãoXYZ
for encontrado, a variável de saída será redefinida para apontar para o novo arquivo ({out="file2}"
) que será usado como destino para imprimir as linhas de dados subsequentes.Referências:
fonte
Este é um trabalho para
csplit
:seria
s
ilently dividir o arquivo, criando peças com préf
ixfile
en
umbered usando um único dígito, por exemplofile0
etc. Note que usar/regex/
iria dividir até, mas não incluindo a linha que partidasregex
. Para dividir até e incluindo a linha correspondente,regex
adicione um+1
deslocamento:Isso cria dois arquivos
file0
efile1
. Se você absolutamente precisar que eles sejam nomeadosfile1
efile2
sempre poderá adicionar um padrão vazio aocsplit
comando e remover o primeiro arquivo:cria
file0
,file1
efile2
masfile0
é vazio assim que você pode removê-lo com segurança:fonte
Com um moderno,
ksh
aqui está uma variante do shell (ou seja, semsed
) de uma dassed
respostas baseadas acima:E outra variante
ksh
sozinha (ou seja, também omitindo ocat
):(A
ksh
solução pura parece ter um bom desempenho; em um arquivo de teste de 2,4 GB, foram necessários 19 a 21 segundos, em comparação com 39 a 47 segundos com a abordagemsed
/cat
).fonte
read
eprint
- você deve deixá-lo sair sozinho. O desempenho melhora se você compilar o kit de ferramentas AST completamente eksh
compilar todos os componentes internos - é estranho para mim quesed
não seja um deles, na verdade. Mas com coisas comowhile <file do
eu acho que você não precisased
tanto ...awk
desempenho no seu benchmark? E enquanto eu tenho certezaksh
que provavelmente sempre vencerá essa luta, se você estiver usando um GNU com osed
qual não está sendo muito justosed
- o-u
nbuffered do GNU é uma abordagem pobre para o POSIXLY, garantindo que o deslocamento do descritor seja deixado onde o programa é encerrado ele - não deve haver necessidade de retardar a operação regular do programa - o buffer está bom - tudo osed
que você precisa fazer é procurar o descritor quando terminar. Por qualquer motivo, o GNU reverte essa mentalidade.while
; a impressão é implicitamente feita como o efeito colateral definido do<##
operador de redirecionamento. E apenas a linha correspondente precisa de impressão. (Dessa forma, a implementação do recurso de shell é mais flexível para suporte a incl./excl.) Umwhile
loop explícito que eu esperaria ser significativamente mais lento (mas não foi verificado).head
vez doread
; ele parece ser apenas um pouco mais lento, mas de código terser:{ head -1 <##XYZ ; { read <##"" ;} >file4 ;} <largefile >file3
.Com o GNU,
sed
você deve usar o-u
switch nbuffered. A maioria dos outrossed
só deve funcionar.Para deixar XYZ de fora ...
fonte
Tente isso com o GNU sed:
fonte
sed -e '1,/XYZ/{w file1' -e 'd}' large_file > file2
Um truque fácil é imprimir em STDOUT ou STDERR, dependendo se o padrão de destino foi correspondido. Você pode usar os operadores de redirecionamento do shell para redirecionar a saída adequadamente. Por exemplo, no Perl, supondo que o arquivo de entrada seja chamado
f
e os dois arquivos de saídaf1
ef2
:Descartando a linha que corresponde ao padrão de divisão:
Incluindo a linha correspondente:
Como alternativa, imprima em diferentes identificadores de arquivo:
Descartando a linha que corresponde ao padrão de divisão:
Incluindo a linha correspondente:
fonte