Respostas:
Com sed
, assim:
sed '20,37d; 45d' < input.txt > output.txt
Se você quiser fazer isso no local:
sed --in-place '20,37d; 45d' file.txt
This option specifies that files are to be edited in-place. GNU
sed 'faz isso criando um arquivo temporário e enviando a saída para esse arquivo e não para a saída padrão.` ... Eu não conheço nenhum outro 'sed', mas a logística da atualização "no local" com um editor de fluxo não "calcula" :)
Se o arquivo couber confortavelmente na memória, você também pode usá-lo ed
.
Os comandos são bem parecidos com o sed
acima, com uma diferença notável : você precisa passar a lista de números de linhas / faixas a serem excluídas em ordem decrescente (da linha mais alta sem / faixa para a mais baixa). O motivo é que, quando você exclui / insere / divide / une linhas ed
, o buffer de texto é atualizado após cada subcomando, portanto, se você excluir algumas linhas, o restante das linhas a seguir não estará mais na mesma posição no buffer quando o o próximo subcomando é executado. Então você tem que começar de trás para frente 1 . Edição no
local :
ed -s in_file <<IN
45d
20,37d
w
q
IN
ou
ed -s in_file <<< $'45d\n20,37d\nw\nq\n'
ou
printf '%s\n' 45d 20,37d w q | ed -s in_file
Substitua w
rite por ,p
rint se desejar imprimir a saída resultante em vez de gravar no arquivo. Se você deseja manter intacto o arquivo original e gravar em outro arquivo, pode passar o novo nome do arquivo para o w
subcomando rite:
ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN
1
A menos que você esteja disposto a calcular os novos números de linha após cada d
exclusão, o que é bastante trivial para este caso em particular (após excluir as linhas 20-37, ou seja, 18 linhas, a linha 45 se torna a linha 27) para que você possa executar:
ed -s in_file <<IN
20,37d
27d
w
q
IN
No entanto, se você precisar excluir vários números / faixas de linha, trabalhar para trás não é um acéfalo.
q
comando é útil no final? Eu acho que sai de qualquer maneira.
Apenas leia na memória, altere e depois escreva de volta. Você pode fazer algo como
filename = "foo"
f = open(filename, 'r+')
linenums = [1, 3]
s = [y for x, y in enumerate(f) if x not in [line-1 for line in linenums]]
f.seek(0)
f.write(''.join(s))
f.truncate(f.tell())
f.close()
Testado com um arquivo de 5 linhas. Créditos para http://pleac.sourceforge.net/pleac_python/fileaccess.html , consulte a seção "Modificando um arquivo no local sem um arquivo temporário". Consulte também https://stackoverflow.com/questions/125703/how-do-i-modify-a-text-file-in-python
Algumas notas:
Pode-se primeiro truncar o arquivo, depois escrever nele, em vez de escrever e depois truncar, como acima. No entanto, não conheço um sinalizador Python que permita a leitura e, em seguida, faça uma gravação truncada. Mas talvez esteja faltando alguma coisa, pois o documento não está tão claro. O que me leva a
Às vezes, a documentação do Python é realmente péssima. Consulte http://docs.python.org/library/functions.html#open
Os modos 'r +', 'w +' e 'a +' abrem o arquivo para atualização (observe que 'w +' trunca o arquivo).
Isso significa alguma coisa para você? O que diabos está "aberto para atualização"?
Eu não sei se fazer isso em python em vez de algo unixy como o editor de fluxo é melhor. Pode ser mais portátil, mas não sei como o sed é portátil. Eu escrevi assim porque me sinto mais à vontade com a programação de baixo nível do que com as ferramentas clássicas do Unix, que são boas se elas fazem exatamente o que você deseja, mas (eu acho) geralmente são menos flexíveis.
Essa abordagem (manipular o arquivo na memória) troca a memória por espaço em disco. Ele deve funcionar bem em máquinas com alguns Gb de memória para arquivos de até algumas centenas de Mb. O Python não lida com seqüências de caracteres com muita eficiência, portanto, mudar para C / C ++, por exemplo, aumentaria um pouco o desempenho e reduziria bastante o uso de memória.
Você pode usar o Vim no modo Ex:
ex -sc '20,37d|45d|x' file
d
excluir
x
salvar e fechar