Python/Perlからdiffコマンドを起動して2つの文字列の差分を表示
PythonまたはPerlからfork, execしてdiffコマンドを起動し、2つの文字列の差分を表示させるサンプルコードです。
diffコマンドへの文字列受け渡しは名前付きパイプを使っています。diffしたいだけなのに3つも子プロセスを起動しちゃってます。
Python
import os import sys import tempfile def execDiff(content1, content2, name1 = "1", name2 = "2"): sys.stdout.flush() # execDiff呼び出す前に標準出力のバッファリングが残っていると # fork後に重複して出力される # FIFOを置くテンポラリディレクトリ作成 tmpdir = tempfile.mkdtemp() # FIFO作成 fifo1 = tmpdir + "/" + name1 fifo2 = tmpdir + "/" + name2 os.mkfifo(fifo1) os.mkfifo(fifo2) # diffコマンド起動 pid = os.fork() if pid == 0: os.execvp("diff", ["diff", "-u", fifo1, fifo2]) # 2つの文字列をdiffコマンドに渡すためのプロセスをfork pid1 = os.fork() if pid1 == 0: writer1 = open(fifo1, "w") writer1.write(content1) writer1.close() sys.exit() pid2 = os.fork() if pid2 == 0: writer2 = open(fifo2, "w") writer2.write(content2) writer2.close() sys.exit() # 子プロセス終了まで待機 os.waitpid(pid1, 0) os.waitpid(pid2, 0) os.waitpid(pid, 0) # FIFOとテンポラリディレクトリ削除 os.remove(fifo1) os.remove(fifo2) os.rmdir(tmpdir) execDiff("abc\nghi\n", "abc\ndef\nghi\n", "before", "after")
$ python sample.py --- /tmp/tmpvvdrq8yq/before 2021-02-28 18:16:39.715880739 +0900 +++ /tmp/tmpvvdrq8yq/after 2021-02-28 18:16:39.715880739 +0900 @@ -1,2 +1,3 @@ abc +def ghi
Perl
use POSIX qw/mkfifo/; use File::Temp qw/tempdir/; sub execDiff { my ($content1, $content2, $name1, $name2) = @_; $name1 = "1" unless defined($name1); $name2 = "2" unless defined($name2); # FIFOを置くテンポラリディレクトリ作成 my $tmpdir = tempdir(); # FIFO作成 my $fifo1 = "$tmpdir/$name1"; my $fifo2 = "$tmpdir/$name2"; mkfifo($fifo1, 0700) or die $!; mkfifo($fifo2, 0700) or die $!; # diffコマンド起動 my $pid = fork; die $! unless defined($pid); if ($pid == 0) { exec("diff", "-u", $fifo1, $fifo2); } # 2つの文字列をdiffコマンドに渡すためのプロセスをfork my $pid1 = fork; die $! unless defined($pid1); if ($pid1 == 0) { open(my $writer1, ">", $fifo1) or die $!; print $writer1 $content1; close($writer1); exit(0); } my $pid2 = fork; die $! unless defined($pid2); if ($pid2 == 0) { open(my $writer2, ">", $fifo2) or die $!; print $writer2 $content2; close($writer2); exit(0); } # 子プロセス終了まで待機 waitpid($pid, 0); waitpid($pid1, 0); waitpid($pid2, 0); # FIFOとテンポラリディレクトリ削除 unlink($fifo1); unlink($fifo2); rmdir($tmpdir); } execDiff("abc\nghi\n", "abc\ndef\nghi\n", "before", "after");
$ perl sample.pl --- /tmp/i4YAOgOSeh/before 2021-02-28 18:16:56.985034423 +0900 +++ /tmp/i4YAOgOSeh/after 2021-02-28 18:16:56.985034423 +0900 @@ -1,2 +1,3 @@ abc +def ghi