我想从File1中提取File2中不存在的行
文件1
a
b
c
Run Code Online (Sandbox Code Playgroud)
文件2
a
c
Run Code Online (Sandbox Code Playgroud)
所以输出应该是:
b
Run Code Online (Sandbox Code Playgroud)
bash中的一个可能的命令是:
comm -23 <(sort File1) <(sort File2) > File
Run Code Online (Sandbox Code Playgroud)
它在bash中运行得非常好,但我不知道在Python中如何正确实现.
我试过了
import os
os.system("comm -23 <(sort File1) <(sort File2) > File")
Run Code Online (Sandbox Code Playgroud)
并没有奏效.任何提示?
纯python解决方案怎么样?
with open('file1', 'r') as f:
lines1 = set(f.read().splitlines())
with open('file2', 'r') as f:
lines2 = set(f.read().splitlines())
print(lines1.difference(lines2))
Run Code Online (Sandbox Code Playgroud)
或者减少内存开销:
with open('file1') as f, open('file2') as f2:
lines1 = set(map(str.rstrip, f))
print(lines1.difference(map(str.rstrip, f2)))
Run Code Online (Sandbox Code Playgroud)
如果必须使用 shell,请安全地使用:
subprocess.call(['bash', '-c',
'comm -23 <(sort "$1") <(sort "$2") >"$3"', '_',
infile1_name, infile2_name, outfile_name])
Run Code Online (Sandbox Code Playgroud)
也就是说:不要将文件名作为代码的一部分传递,而是将它们作为带外变量传递,这样 shell 就无法解释它们的名称。
继续使用sortand comm,但没有shell,它看起来更像:
from subprocess import Popen, PIPE, call
p_sort1 = Popen(['sort'], stdin=open(infile1_name, 'r'), stdout=PIPE)
p_sort2 = Popen(['sort'], stdin=open(infile2_name, 'r'), stdout=PIPE)
p_comm = Popen(['comm', '-23',
f'/dev/fd/{p_sort1.stdout.fileno()}',
f'/dev/fd/{p_sort2.stdout.fileno()}',
],
pass_fds=[p_sort1.stdout.fileno(), p_sort2.stdout.fileno()],
stdout=open('outfile_name', 'w'),
)
# Close file descriptors on the Python end so only the spawned processes have
# open copies
p_sort1.stdout.close()
p_sort2.stdout.close()
# Let the pipeline run, with comm reading output from the two sort processes
p_comm.wait()
Run Code Online (Sandbox Code Playgroud)
话虽如此,用纯 Python 来做这件事(如MaxNoe 的回答)是理想的;从上面获得的唯一主要优点是sort能够处理大于 RAM 的内容(通过拆分为临时文件并进行合并排序来组合它们)。
| 归档时间: |
|
| 查看次数: |
579 次 |
| 最近记录: |