プロセス置換入力のdiff3は違いを見つけますが、ファイル内の同じデータのdiff3が違いを見つけることができないのはなぜですか?

プロセス置換入力のdiff3は違いを見つけますが、ファイル内の同じデータのdiff3が違いを見つけることができないのはなぜですか?

ファイルのdiff3に違いが見つかりませんでした。

$ grep -P '\[\[.*?\]\]' -o intro.tex | sort > A.txt
$ grep -P '\[\[.*?\]\]' -o intro.tex | sort | uniq > B.txt
$ grep '\\pnum %% \[\[' intro.tex | sed 's/\\pnum %% //' | sort > C.txt
$ diff3 A.txt B.txt C.txt | wc -l
0

diff3 は、同じコマンドを実行するプロセス置換に違いを見つけました。

$ diff3 \
  <(grep -P '\[\[.*?\]\]' -o intro.tex | sort) \
  <(grep -P '\[\[.*?\]\]' -o intro.tex | sort | uniq) \
  <(grep '\\pnum %% \[\[' intro.tex | sed 's/\\pnum %% //' | sort) | wc -l
95

なぜ?どんなアイデアがありますか?

最小再生:

$ echo test > a
$ diff3 a a a
$ diff3 <(cat a) <(cat a) <(cat a)
====1
1:1c
  test
2:0a
3:0a

答え1

diff3私たちが実行している場合strace -f

$ strace -qqfe execve -e signal=none diff3 a b c
execve("/usr/bin/diff3", ["diff3", "a", "b", "c"], 0x7ffef2bb2d78 /* 53 vars */) = 0
[pid 13360] execve("/usr/bin/diff", ["diff", "--horizon-lines=100", "--", "b", "c"], 0x7ffc019c6d50 /* 53 vars */) = 0
[pid 13361] execve("/usr/bin/diff", ["diff", "--horizon-lines=100", "--", "a", "c"], 0x7ffc019c6d50 /* 53 vars */) = 0

ご覧のとおり、2回呼び出さdiff3れ、3diff番目のファイルは両方の呼び出しのオペランドの1つです。

ksh<(...)スタイルのプロセス置換の場合、ファイルはパイプです。

cmd1 <(cmd2)

同じです:

cmd2 | cmd1 /dev/fd/0

ゼロ以外のfdを使用することを除いて。

したがって、3番目の引数の場合、diff3最初の引数は完全なdiff入力を消費し、2番目の引数は読み取ることができないため、ファイルが空であるように見えます。

したがって、少なくとも3番目のパラメータはパイプにすることはできません。

使用している場合は、パイプの代わりに一時ファイルを使用するプロセス代替形式をzsh使用できます。=(...)

diff3 <(cmd1) <(cmd2) =(cmd3)

(最初の2つはまだパイプかもしれません)。

あなたの場合:

$ diff3 \
  <(grep -Po '\[\[.*?\]\]' intro.tex | sort) \
  <(grep -Po '\[\[.*?\]\]' intro.tex | sort -u) \
  =(sed -n 's/\\pnum %% \[\[/[[/p' intro.txt | sort)

(重複も削除し、grepオプションを非オプションの前にuniq移動しました。)-o

以下を使用して因数分解することもできます。

(){ diff3 $1 <(uniq<$1) $2; } =(grep -Po '\[\[.*?\]\]' intro.tex) \
                              =(sed -n 's/\\pnum %% \[\[/[[/p' intro.txt | sort)

1 3番目の引数がstdinを読み取ると-解釈されると、diff32番目の引数はパイプになりません。diffこの場合、両方の呼び出しにパイプが渡されるためです。このマニュアルには次の内容が記載されています。たくさんあるべきこれら3つのファイル名の1つは、標準入力にそのファイルを読み取るように指示すること-です。diff3

関連情報