こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

awkの入力ファイルをリダイレクト先にする方法

---------hoge.txt---------
hoge
hoge
hoge
-------------------------
等としておいて、
$ awk '{print NR":"$1;}' hoge.txt
とすると標準出力に
-------------------------
1:hoge
2:hoge
3:hoge
-------------------------
と表示されますが、これを
$ awk '{print NR":"$1;}' hoge.txt > hoge.txt
と自分自身にリダイレクトするとhoge.txtは空になってしまいます。
hoge.txtに上の標準出力を上書きするにはどのように書けば良いのでしょうか、教えてください。

awkだけでなく、テキストファイルを入力にできるコマンド一般についても
上記のようなことができる方法があれば、教えていただきたいです。

投稿日時 - 2008-03-17 23:18:29

QNo.3872133

暇なときに回答ください

質問者が選んだベストアンサー

これはawkの(またその他のコマンドの)問題ではありません。
awkからは標準入力と標準出力か見えておらず、それがどういう名前のファイルに
結びつけられているかはawkのあずかり知らない世界の話です。

Shell Command Language
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html

にシェルのリダイレクトの仕様の記述があります。

2.7.1 Redirecting Input

Input redirection shall cause the file whose name results from the expansion of word to be opened for reading on the designated file descriptor, or standard input if the file descriptor is not specified.

The general format for redirecting input is:

[n]<word

where the optional n represents the file descriptor number. If the number is omitted, the redirection shall refer to standard input (file descriptor 0).
2.7.2 Redirecting Output

The two general formats for redirecting output are:

[n]>word
[n]>|word

where the optional n represents the file descriptor number. If the number is omitted, the redirection shall refer to standard output (file descriptor 1).

Output redirection using the '>' format shall fail if the noclobber option is set (see the description of set -C) and the file named by the expansion of word exists and is a regular file. Otherwise, redirection using the '>' or ">|" formats shall cause the file whose name results from the expansion of word to be created and opened for output on the designated file descriptor, or standard output if none is specified. If the file does not exist, it shall be created; otherwise, it shall be truncated to be an empty file after being opened.

シェルがリダイレクト元のファイルの中身を読み込んでそれをコマンドに
送るのではなく、ファイルをオープンしてそのファイルディスクリプタを
すげ替えるという形でリダイレクトは実現されています。
出力のリダイレクトの方に、
If the file does not exist, it shall be created; otherwise, it shall be truncated to be an empty file after being opened.
とありますから、入力を先にオープンしていようが後にオープンしていようが
出力リダイレクトの処理をした時点でファイルの中身は消されてしまうので
実際に読み込みを行ったときにはもはや何もない。ということです。


hp-uxのドキュメントに以下のような記述がありました

標準入力、標準出力、標準エラー出力の理解
"標準入力と標準出力両方のリダイレクト

1 つのコマンドの標準入力と標準出力の両方とも、リダイレクトすることもできます。ただし、標準入力と標準出力に同じファイル名を使用してはいけません。上書きされて、入力ファイルの元の内容が失われてしまいます。"
http://docs.hp.com/ja/B2355-90813/ch03s03.html

投稿日時 - 2008-03-19 23:53:03

お礼

なるほど、リダイレクトの仕様なのですね。よく分かりました。
私の質問したようなことを実現するリダイレクトの方法はないということなので、
1)コマンドオプションがあればそれを使うか、
2)なければ別のファイルに出力してリネームするという方法をとることにします。
ありがとうございます。

投稿日時 - 2008-03-20 01:58:27

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

繰り返し質問されることですが、これはどうしようもありません。
コマンドによっては、入力ファイルを上書きするオプションを持っている(GNU sedとか)ものもありますが、
一度別のファイルに書き出しておいて、リネームするなどするよりないでしょう。

投稿日時 - 2008-03-19 12:36:14

補足

-------------------------
#!/bin/sh
awk '{print NR":"$1;}' hoge.txt > hoge.txt~
mv hoge.txt~ > hoge.txt
-------------------------
のようなスクリプトを作るしかないのでしょうか。なんだかとっても無駄なことをしている気がしてならないです。
awkでは無理だと断言している資料をまだ見付けられていないので、そういうサイトなり本なりがあれば教えていただきたいです。よろしくお願いします。

投稿日時 - 2008-03-19 15:58:17

あなたにオススメの質問