見ているこの問題awk
、ファイルが標準入力にパイプされていると、ユーザー入力を読み取ることはできませんが、コマンドライン引数として指定されたファイルから入力を読み取ることが期待どおりに機能することを確認しました。
たとえば、スクリプトに次のBEGINブロックがあるとしますawk
。
BEGIN {
printf "Enter input: "
getline var < "-"
}
これを実行すると、awk -f ./script.awk file.txt
ユーザーに入力するように求められ、処理が続行されますfile.txt
。ただし、これを実行すると、cat file.txt | awk -f ./script.awk
awkがパイプから取得した内容をユーザー入力として解釈すると考えられます(したがって、最初の行がgetline
埋められます)。var
file.txt
awk
ファイルから読み取るように動作しますが、パイプで使用する方法はありますか?
もちろん、一時ファイルを使用することもできますが、これはエレガンスから離れています。
答え1
プロセスの置き換えは簡単な場合には機能しますが、パイプデータを処理しながらコンソールユーザーと対話できる一般的なアプローチは次のとおりです。
BEGIN {
printf "Enter input: " > "/dev/tty"
getline var < "/dev/tty"
print var
}
答え2
一時ファイルに加えて、プロセス置換のためのシェルのサポートを使用することもできます(これはbash
、zsh
またはいくつかの実装ksh
(この機能はksh88で導入されている)と仮定します)。
awk -f ./script.awk <(cat file.txt)
これは、読み込み時に添付されたコマンドの出力を含む構文の代わりにawk
ファイル名を提供します。<(...)
答え3
これがあなたのワークフローに適している場合は、awk自体がパイプを開くようにすることができます。 Elementsではこれを行うことができないため、ARGV
パイプから読み取った行からawkの自動反復を取得することはできません。代わりに、awkはコマンドライン引数として渡されたファイルから読み取るか、ファイル引数がない場合は標準入力から読み込みます。
{
printf "Enter input: "
getline var
while (("cat file.txt" | getline) > 0) { … }
}
この構造はあなたのおもちゃの例には合いませんが、実際の問題に合う可能性があるので言及します。
答え4
システムが/dev/fd/[num]
接続をサポートするawk
かGNUの場合は、次awk
のように機能しますawk -f ./script.awk file.txt
。
{ some_cmd | 3<&0 <&4 4<&- awk -f ./script.awk /dev/fd/3; } 4<&0