一時ファイル生成、プロセス置換、変数拡張?

一時ファイル生成、プロセス置換、変数拡張?

私が次のようなことをしていたら

  1. 一時ファイルの作成

    some process generating output > temp_file
    cat  temp_file
    
  2. プロセスの交換:

    cat <(some process generating output)
    
  3. 他の方法:

    cat <<<(some process generating output)
    

これについていくつかの質問があります。

  1. <() >()プロセス置換や変数拡張のためのデータ出力サイズに制限はありますか?<<<()
  2. 次のうち最も速いものは何ですか?それとももっと速くする方法はありますか?

私のulimitコマンドの出力は次のとおりです。

bash-3.00$ ulimit -a
core file size        (blocks, -c) unlimited
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
open files                    (-n) 256
pipe size          (512 bytes, -p) 10
stack size            (kbytes, -s) 8480
cpu time             (seconds, -t) unlimited
max user processes            (-u) 8053
virtual memory        (kbytes, -v) unlimited

ベストアンサー1

<(cmd)またksh今は、zshbashプロセスの交換

/dev/fd/nまたは をサポートするシステムでは、/proc/self/fd/n一時的な名前付きパイプではなくパイプを介して実装されます。とにかく、それはプロセス間通信メカニズムであるパイプの形です。

cmd1 <(cmd2)

(通常のパイプを使用して)次のように書くことができます。

{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0

または(名前付きパイプを使用):

mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe

つまり、両方のコマンドが同時に開始され、パイプと通信します。通常、これを実行しますcmd2 | cmd1が、プロセス置換は標準入力ではなくファイル名からのみ入力を取得できcmd1ますdiff <(cmd1) <(cmd2)

プロセス数、CPU 時間、メモリなどの一般的な制限に加えて、他の制限は影響しません。

ulimitPIPEBUFのいくつかの実装と同様のbashレポートでは、PIPEBUFkshはrlimitではありませんが、パイプへの書き込みが原子的に保証される最大サイズであるため、これには関係ありません。パイプ自体のサイズ(Linuxでは@dsmsk80が64kBを報告する)自体は実際に制限ではありません。cmd2パイプから読み取りを中断した後もパイプに書き込むことができると言います。cmd1

cmd1しかし、読むこのファイルから。パイプなので、ファイルに書き込んだり、ファイルを前後に表示したりすることはできません。

zsh通常の一時ファイルを使用する3番目の形式のコマンド置換があります。

cmd1 =(cmd2)

cmd1呼び出しは、出力を含む一時ファイルで行われますcmd2。この場合cmd1実行後ろに同時代わりにcmd2。ファイルサイズ制限に達する可能性があります。

<<<(...)私は演算子を実装するシェルを知りません。しかし、(Unixポートの同じ演算子からインスピレーションを得た)<<<演算子は、およびの最新バージョンでも見つかります。zshこれはherestringと呼ばれるheredoc演算子のバリアントです。rcksh93bash<<

存在する:

cmd <<< something

標準と同じ:

cmd << EOF
something
EOF

シェルは一時ファイルをsomething\nコンテンツとして生成し、それを新しいプロセスに標準入力として提供し、ファイルのリンクを解除してcmd新しいプロセスで実行します。繰り返しますが、これは通常のファイルなので、最大ファイルサイズ制限に達する可能性があります。

これで、<<<演算子を(コマンドの置き換え)と組み合わせて、任意$(...)の方法で演算子をエミュレートできますzsh=(...)bashksh93

cmd1 <<<"$(cmd2)"

cmd2パイプにリダイレクトされた標準出力として実行されます。パイプのもう一方の端では、シェルは出力を読み取り、末尾の改行をcmd2除いて保存し、一時ファイルに改行を追加し、その一時ファイルを呼び出してcmd1stdinで読み取るために開きます(別の制限があることに注意してください)にNUL文字が含まれていると機能しませんcmd2

ようになるには、=(...)次のように書く必要があります。

cmd1 /dev/fd/3 3<<<"$(cmd3)"

シェルは一時ファイルに書き込む前にメモリ内のcmd3の出力全体を読み取る必要があるため、最大ファイルサイズに加えてメモリ使用量の制限に達することがあります。

また、バージョン 5 以降では、bash呼び出し前に一時ファイルへの書き込み権限が削除されるため、ファイルを変更する必要があるcmd1場合は、cmd1次の方法で問題を解決する必要があります。

{
  chmod u+w /dev/fd/3 && # only needed in bash 5+
  cmd1 /dev/fd/3
} 3<<<"$(cmd3)"

おすすめ記事