如何删除文件中的某些行(使用行号)?


27

我要从文件中删除某些特定行。假设这是第20-37行,然后是第45行。如果不指定这些行的内容,该怎么办?


您的文件有多大?可以加载到内存中吗?
Faheem Mitha

几千字节。
tshepang 2011年

Answers:


29

使用sed,如下所示:

sed '20,37d; 45d' < input.txt > output.txt

如果您想就地执行此操作:

sed --in-place '20,37d; 45d' file.txt

有一种就地执行的方法吗?
tshepang 2011年

我建议使用sed -i文件
enzotib 2011年

1
@Tshepang:使用ed,或GNU sed的-i,或者sponge,或者一个大文件的方法
吉尔(Gilles)“所以,别再邪恶了”,

3
当提到“ sed”时,我经常想知道in-place这个可能引起误解的术语,因此我在“ man sed”中查找它:-- in -place [= SUFFIX]This option specifies that files are to be edited in-place. GNU sed'通过创建一个临时文件来完成此操作并将输出发送到此文件,而不是发送到标准输出。`...我不知道任何其他“ sed”,但使用编辑器更新“就地”的后勤工作不“计算” :)
Peter.O 2011年

2
根据我的经验,大多数“就地”方法都使用一个临时文件。
Faheem Mitha

5

如果文件适合存储在内存中,则也可以使用ed
这些命令与sed上面的命令非常相似,但有一个显着的区别:您必须以降序传递要删除的行号/范围列表(从最高的行号/范围到最低的行号/范围)。原因是,当您使用删除/插入/分割/合并行时ed,在每个子命令之后都会更新文本缓冲区,因此,如果删除某些行,则当下一个子命令被执行。所以你必须倒退1
就地编辑:

ed -s in_file <<IN
45d
20,37d
w
q
IN

要么

ed -s in_file <<< $'45d\n20,37d\nw\nq\n'

要么

printf '%s\n' 45d 20,37d w q | ed -s in_file

如果要打印结果输出而不是写入文件,则将write用,print 替换。如果要保持原始文件不变并写入另一个文件,可以将新文件名传递给write子命令:

ed -s in_file <<IN
78,86d
65d
51d
20,37d
w out_file
q
IN

1 除非您愿意在每次d删除之后计算新的行号,这对于这种特殊情况来说是微不足道的(删除第20-37行,即18行,第45行成为第27行),因此可以运行:

ed -s in_file <<IN
20,37d
27d
w
q
IN

但是,如果您必须删除多个行号/范围,那么倒退工作就很容易了。


q命令最后有用吗?我想它都会退出。
汤姆·费内奇

@TomFenech-并不是所有的实现都以任何一种方式退出(尽管大多数实现都退出了……我再也找不到讨论该主题的线程了……)
don_crissti

1

只需将其读入内存,对其进行更改,然后将其写回即可。你可以做类似的事情

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()

经过5行文件测试。感谢http://pleac.sourceforge.net/pleac_python/fileaccess.html的帮助,请参阅“在没有临时文件的情况下就地修改文件”一节。另请参阅/programming/125703/how-do-i-modify-a-text-file-in-python

一些注意事项:

  1. 如上所述,可以先截断文件,然后写入文件,而不是写入,然后截断文件。但是,我不知道一个Python标志允许一个人读取然后进行截断的写入。但是也许我缺少一些东西,因为文档不够清晰。这带给我

  2. 有时Python文档确实很烂。请参阅 http://docs.python.org/library/functions.html#open

    模式“ r +”,“ w +”和“ a +”打开文件进行更新(请注意,“ w +”会截断文件)。

    这对您有什么意义吗?“开放更新”到底是什么?

  3. 我不知道在python中这样做,而不是像流编辑器这样的unixy更好。它可能更便携,但我不知道sed的便携性。我之所以这样写是因为,与使用经典的unix工具相比,我对低级编程更满意,如果它们确实可以满足您的要求,则很好,但是(我认为)通常不太灵活。

  4. 这种方法(操作内存中的文件)将内存换为磁盘空间。它在具有几Gb内存的机器上可以正常工作,文件大小高达几百Mb。Python不能非常有效地处理字符串,因此,例如切换到C / C ++会稍微提高性能并大大减少内存使用。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.