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/2
gawk
/dev/fd/x
/dev/stderr
以下を行うとき:
print "x" > "/dev/fd/2"
gawk
Execute の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/fd
Linuxに固有のもので、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
ロードしようとすると、誰かがそのディレクトリにマルウェアを植えた可能性があります。システムに付属の拡張プログラムのパスは異なる場合があります。出力を参照してください。inplace
inplace
inplace.awk
inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'
答え2
楽しみにしてもう一つのアプローチはfind
、sh
および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 {} +
:)
(このコマンドはテストされていません。間違えた場合は自由に編集してください。)