固定および標準出力

固定および標準出力

gawk's-i inplaceオプションを使用してコンテンツを印刷できますかstdout

たとえば、ファイルを更新し、変更があった場合にファイル名と変更された行を印刷するには、stderr次のようにします。

find -type f -name 'myfiles' -exec gawk -i inplace '{if(gsub(/pat/, "repl")) { print FILENAME > "/proc/self/fd/2" ; print > "/proc/self/fd/2"; } print;}' {} +

stdoutしかし、そのブロックを代替ストリームとして印刷する代替方法またはよりきれいな方法はありますか?

答え1

およびそれ自体を処理するには(システムにこれらのファイルがあるかどうかにかかわらず)、代わりに/dev/stderrまたはを使用する必要があります。/dev/fd/2/proc/self/fd/2gawk/dev/fd/x/dev/stderr

以下を行うとき:

print "x" > "/dev/fd/2"

gawkExecute のwrite(2, "x\n")実行中:

print "x" > "/proc/self/fd/2"

特別な処理がないので、/proc/self/fd/x次のことを行います。

fd = open("/proc/self/fd/2", O_WRONLY|O_CREAT|O_TRUNC);
write(fd, "x\n");

最初のものは/proc/self/fdLinuxに固有のもので、Linuxではバグがあります。上記の2つのバージョンは、stderrが通常のファイルであるか、他の検索可能なファイルまたはソケットの場合(後者は失敗する)と同じではありません(ファイル記述子を無駄にすることは言うまでもありません)。

ただし、生のstdoutに書き込む必要がある場合は、次のように別のfdに保存する必要があります。

gawk -i /usr/share/awk/inplace.awk '{
   print "goes into the-file"
   print "to stdout" > "/dev/fd/3"}' the-file 3>&1

gawk実際にはstdoutをファイルにリダイレクトします。たとえば、次のものが必要なので必要です。

awk -i /usr/share/awk/inplace.awk '{system("uname")}' file

uname出力をに保存しますfile

いずれにせよ、使用しないでください-i inplace現在の作業ディレクトリから最初に拡張機能をgawkロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplaceinplaceinplace.awkinplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答え2

楽しみにしてもう一つのアプローチはfindshおよびgrep(最も注目すべき)POSIX関数のみを使用しますex

find . -type f -name 'myfiles' -exec sh -c '
  for f do grep -q "pat" "$f" &&
    { printf "%s\n" "$f";
      printf "%s\n" "%s/pat/repl/g" x | ex "$f";
  }; done' find-sh {} +

(上記のコマンドのすべての改行はオプションであるため、1行に圧縮できます。)

または、より明確に言えば、

find . -type f -name 'myfiles' -exec sh -c '
  for f
  do
    if grep -q "pat" "$f"; then
      printf "%s\n" "$f"
      printf "%s\n" "%s/pat/repl/g" x | ex "$f"
    fi
  done' find-sh {} +

:)


(このコマンドはテストされていません。間違えた場合は自由に編集してください。)

関連情報