Eu tenho o cenário em que as linhas a serem adicionadas no início e no final dos arquivos enormes.
Eu tentei como mostrado abaixo.
para a primeira linha:
sed -i '1i\'"$FirstLine" $Filename
para a última linha:
sed -i '$ a\'"$Lastline" $Filename
Mas o problema com este comando é que ele está anexando a primeira linha do arquivo e atravessando o arquivo inteiro. Para a última linha, é novamente percorrendo o arquivo inteiro e anexando uma última linha. Como seu arquivo muito grande (14 GB) está demorando muito tempo.
Como posso adicionar uma linha ao início e outra ao final de um arquivo enquanto apenas o leio uma vez?
fonte
for
loop:for file in Tes*; do [command]; done
"$file"
, nãoTes*
como argumentoed
.Observe que, se você quiser evitar a alocação de uma cópia inteira do arquivo no disco, poderá:
Isso usa o fato de que, quando seu stdin / stdout é um arquivo,
sed
lê e grava em bloco. Portanto, aqui, não há problema em substituir o arquivo que está lendo, desde que a primeira linha que você está adicionando seja menor quesed
o tamanho do bloco (deve ser algo como 4k ou 8k).Observe que, se por algum motivo
sed
falhar (morte, falha na máquina ...), você terminará com o arquivo meio processado, o que significa que alguns dados do tamanho da primeira linha estão ausentes em algum lugar no meio.Observe também que, a menos que você
sed
seja o GNUsed
, isso não funcionará para dados binários (mas como você está usando-i
, você está usando o GNU sed).fonte
Aqui estão algumas opções (que criarão uma nova cópia do arquivo, verifique se você tem espaço suficiente para isso):
eco simples / gato
awk / gawk etc
awk
e seus arquivos de leitura ilk linha por linha. OBEGIN{}
bloco é executado antes da primeira linha e oEND{}
bloco após a última linha. Então, o comando acima significaprint "first" at the beginning, then print every line in the file and print "last" at the end
.Perl
Isso é essencialmente a mesma coisa que o gawk acima, escrito em Perl.
fonte
sed -i
que cria arquivos temporários.Eu prefiro o muito mais simples:
Isso transforma o arquivo:
para o arquivo:
fonte
Você pode usar o Vim no modo Ex:
1
selecione a primeira linhai
inserir texto e nova linha$
selecione a última linhaa
acrescentar texto e nova linhax
salvar e fecharfonte
Não há como inserir dados no início de um arquivo¹, tudo o que você pode fazer é criar um novo arquivo, gravar os dados adicionais e anexar os dados antigos. Portanto, você terá que reescrever o arquivo inteiro pelo menos uma vez para inserir a primeira linha. Você pode acrescentar a última linha sem reescrever o arquivo.
Como alternativa, você pode combinar os dois comandos em uma corrida de sed.
sed -i
cria um novo arquivo de saída e o move sobre o arquivo antigo. Isso significa que, enquanto o sed estiver trabalhando, há uma segunda cópia do arquivo usando espaço. Você pode evitar isso substituindo o arquivo no local , mas com restrições importantes: a linha que você está adicionando deve ser menor que o buffer do sed e, se o sistema travar, você terminará com um arquivo danificado e com algum conteúdo perdido no meio, então eu recomendo fortemente contra isso.¹ O Linux tem uma maneira de inserir dados em um arquivo, mas só pode inserir um número inteiro de blocos do sistema de arquivos, não pode inserir seqüências de caracteres de comprimentos arbitrários. É útil para alguns aplicativos, como bancos de dados e máquinas virtuais, mas é inútil para arquivos de texto.
fonte
fallocate()
comFALLOC_FL_INSERT_RANGE
disponível no XFS e ext4 nos kernels modernos (4.xx) man7.org/linux/man-pages/man2/fallocate.2.htmlfonte
Os modernos kernels do Linux (superiores a 4.1 ou 4.2) suportam a inserção de dados no início de um arquivo através da
fallocate()
chamada do sistemaFALLOC_FL_INSERT_RANGE
nos sistemas de arquivos ext4 e xfs. Em essência, esta é uma operação de mudança lógica: os dados são realocados logicamente com um deslocamento mais alto.Existe uma restrição em relação à granularidade do intervalo que você deseja inserir no início do arquivo. Mas para arquivos de texto, você provavelmente pode alocar um pouco mais do que o necessário (até o limite da granularidade) e preencher com espaços ou retornos de carro, mas isso depende do seu aplicativo
Não conheço nenhum utilitário linux prontamente disponível que manipule extensões de arquivo, mas não é difícil escrever: obtenha um descritor de arquivo e chame
fallocate()
com os argumentos apropriados. Para mais detalhes, consulte a página de manual dafallocate
chamada do sistema: http://man7.org/linux/man-pages/man2/fallocate.2.htmlfonte
fallocate
utilitário -linux contém um utilitário. O problema é que uma granularidade de blocos inteiros torna isso inútil para a maioria dos arquivos de texto. Outro problema é que a alocação do intervalo e a modificação subsequente não são atômicas. Portanto, isso realmente não resolve o problema aqui.fallocate
atomicidade é interrompida, por favor, estou curioso)