1

この一連のコマンドを Python プログラム内から実行したいと思います。

wc -l <(comm -12 <(sort file1.txt) <(sort file2.txt))

私は次のことで成功しました:

sort_a = Popen("sort file1.txt", shell=False, stdout=PIPE)
count = Popen(["wc", "-l"], shell=False, stdout=PIPE, stdin=sort_a.stdin)

複数の stdout を comm -12 の stdin にリダイレクトする方法を理解できていません。

私はおそらく考えました:

compare = Popen(["comm", "-12"], shell=False, stdout=PIPE, stdin=[sort_a.stdin, sort_b.stdin])

考え?

4

1 に答える 1

1

まず、シェルの<(command)コマンド置換がどのように機能するかを見てみましょう。コマンドは、新しく作成されたパイプを指す出力で開始されます。次に、パイプはコマンドラインでファイル名として外部コマンドに渡されます。

例えば:

$ echo wc -w <(date)
wc -l /dev/fd/63

シェルがdateパイプへの出力から開始し、/dev/fd/63ファイル記述子 63 で新しいパイプを参照する疑似ファイルを実際のコマンド ライン引数として渡すことを示します。


Python で同じ動作を得るために、同じことを実装できます。

from subprocess import *

date = Popen(['date'], stdout=PIPE)
Popen(["wc", "-w", "/dev/fd/%d" % date.stdout.fileno()])

印刷する

6 /dev/fd/3

簡単にするためにクラスを書くことができます。これはwithステートメントを使用し、生成された各プロセスへの参照を一時的に保持します。そうしないと、プロセス オブジェクトがガベージ コレクションされたときにパイプが閉じられるためです。

from subprocess import *

class CommandSubstituter(object):
    def __init__(self):
        self._procs = []

    def __enter__(self):
        return self

    def __exit__(self, *exc_info):
        pass

    def subst(self, *args, **kwargs):
        proc = Popen(*args, stdout=PIPE, **kwargs)
        self._procs.append(proc)
        return "/dev/fd/%d" % proc.stdout.fileno()

with CommandSubstituter() as c:
    Popen(['wc', '-l',
           c.subst(['comm', '-12',
                    c.subst(['sort', 'file1.txt']),
                    c.subst(['sort', 'file2.txt'])])])
于 2013-01-22T17:31:41.253 に答える