如何在Python中执行comm Linux命令

jos*_*ski 0 python linux bash

我想从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)

并没有奏效.任何提示?

Max*_*Noe 7

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

  • `set(map(str.rstrip,f))``set(itertools.imap(str.rstrip,f))` (2认同)
  • 它不会在内存中创建潜在的大量数据,你也可以完全忘记在第二个文件上调用set和`set(map(str.rstrip,f)).difference(map(str.rstrip,f2))` ,使用"差异"的意思是你不需要第二个迭代就是一个集合. (2认同)

Cha*_*ffy 5

如果必须使用 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 的内容(通过拆分为临时文件并进行合并排序来组合它们)。