web-dev-qa-db-ja.com

一致する線を反転、NULで区切る

ファイルの一致を処理するものを書いていますが、反転操作が必要です。ファイルのリスト(例:find . -type f -print0 | sort -z >lstから)と一致のリスト(例:grep -z foo lst >matchesから–これは単なる例であることに注意してください; matchesは任意のサブセットにすることができます(空または完全)またはlst)を含み、このリストを反転したいと思います。

背景:ファイルリストを除いて、 find(1) のようなものを実装しています(ファイルは呼び出しの時点でファイルシステムに存在しますが、リストは事前にフィルタリングされている可能性があります)。ファイルのリストがそれほど大きくない可能性がある場合は、find "${files[@]}" -maxdepth 0 -somecondition -print0を使用できますが、私が書いているものを適度に使用しても、LinuxまたはBSDのargvサイズ制限を超えてしまいます。

行がNULで区切られていない場合は、comm -23 lst matches >invertedを使用できます。一致がNULで区切られていない場合は、grep -Fvxzf matches lstを使用できます。しかし、最初の段落で述べたジェネレーターからは、両方ともそうです。

GNUツールがインストールされていると仮定します。したがって、私はすでにfind -print0sort -zとその友人を使用しているので、Debianなどを超えて移植可能である必要はありません(ただし、一部のBSDにはそれがあります)ですから、「よりポータブル」で実行できれば、文句は言いません)。

ここでコードの再利用を試みています。さらに、comm -23は、入力行区切り文字の変更を(まだ)サポートしていないことを除いて、基本的にこれに最適なツールです。 comm は過小評価されており、十分に知られていません。とにかくツール。 Unix/Linuxツールボックスが意味のあるものを何も提供しない場合、スクリプトはすでに(他の理由で)必要なので、シェルでcomm -23の形式(この1つのユースケースに縮小)を再実装する可能性があります。たまたまNULで区切られた入力に対してread -d ''をサポートするシェルですが、それは遅くなります(そして努力…私が明日これを拾うときに誰かがアイデアを持っていることを期待して、これを仕事の終わりに投稿しましたまたは28日)。

4
mirabilos

commが非テキスト入力をサポートしている場合(GNUツールは一般的にサポートしている))、いつでもNULとnlを交換できます(ここではプロセス置換をサポートするシェルを使用しています( mksh btwでその計画を立てますか?)):

comm -23 <(tr '\0\n' '\n\0' < file1) <(tr '\0\n' '\n\0' < file2) |
  tr '\0\n' '\n\0'

それは 一般的なテクニック です。

6