awk 'processing_script_here' my=file.txt
無限に止まって待つ...
ここで何が起こっているのか、そしてどのように機能しますか?
答え1
〜のようにクリスが言う、フォームの引数は、入力ファイル名ではなく変数の割り当て(ステートメントの前に実行された(最新の)変数の割り当てとは異なり、引数が処理されたvariablename=anything
ときに実行されます)として扱われます。-v var=value
BEGIN
これは次のような場合に便利です。
awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2
FS
そこからファイルごとに異なるものを指定できますRS
。また、一般的に次の用途に使用されます。
awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2
より安全なバージョンは次のとおりです。
awk 'NR==FNR{a[$0]; next}; {...}' file1 file2
file1
(空であれば何の効果もありません)
=
ただし、ファイル名に文字が含まれていると問題が発生します。
=
これは、最初の残りの部分が有効な変数名である場合にのみ問題になりますawk
。
では、有効な変数名の設定はawk
からより厳密ですsh
。
POSIXでは、次のようにする必要があります。
[_a-zA-Z][_a-zA-Z0-9]*
移植可能な文字セットの文字のみを使用してください。ただし、/usr/xpg4/bin/awk
Solaris 11は少なくともこの点で互換性がなく、a-zA-Zだけでなく、ロケール内のすべてのアルファベット文字を変数名に使用できます。
x+y=foo
したがって、=bar
or などの引数は、./foo=bar
まだ割り当てではない入力ファイル名として扱われます。最初の引数の残りの部分は=
有効な変数名ではないからです。実装とロケールStéphane=Chazelas.txt
に応じて、「may」や「not」などのパラメータです。awk
そのため、awkを使用するときは、次のものを使用することをお勧めします。
awk '...' ./*.txt
変える
awk '...' *.txt
たとえば、ファイル名に文字がtxt
含まれていないことを保証できない場合は、問題を回避できます=
。
また、以下を-vfoo=bar.txt
使用する場合は、同様のパラメーターをオプションと見なすことができます。
awk -f file.awk -vfoo=bar.txt
(1.28.0より前のbusyboxバージョンにも適用可能ですawk '{code}' -vfoo=bar.txt
。awk
対応するエラーレポート)。
繰り返しますが、./*.txt
この問題は次の方法で解決できます(プレフィックスを使用すると、他の意味で理解されている./
ファイルを呼び出すときにも役立ちます)。-
awk
標準入力代わりに)。
これは理由
#! /usr/bin/awk -f
Shebangsは実際には動作しません。これらの問題はvar=value
次のように解決できますが、固定明細の値ARGV
(./
プレフィックスを追加) BEGIN
:
#! /usr/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++)
if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
ARGV[i] = "./" ARGV[i]
}
# rest of awk script
これはオプションには役立ちません。なぜなら、そのオプションはスクリプトawk
ではなくawk
スクリプトによって表示されるからです。
この接頭辞を使用するときに./
発生する可能性のある外観上の問題の1つはで終わることです。ただし、不要な場合はFILENAME
いつでもこのプレフィックスを使用して削除できます。substr(FILENAME, 3)
GNU実装はawk
オプションを介してこれらすべての問題を解決します-E
。
その後、-E
gawkはスクリプトパスawk
(-
まだstdinを意味します)と入力ファイルパスのリストのみを期待します(-
特別な処理もしません)。
これは以下のために設計されています:
#! /usr/bin/gawk -E
引数リストが常に入力ファイルであるshebangs(ARGV
ステートメント内でリストを自由に編集できることに注意してくださいBEGIN
)。
次のように使用することもできます。
gawk -e '...awk code here...' -E /dev/null *.txt
後続のスクリプトに文字が含まれていても、常に入力ファイルとして処理されるように空の-E
スクリプト()を使用します。/dev/null
*.txt
=
答え2
ほとんどのawkバージョンで実行されるプログラムの後に続くパラメータは次のとおりです。
- 1つの文書
- テーブルの割り当て
x=y
ファイル名はケース#2として解釈されるため、awkはまだstdinが何かを読むのを待っています(ファイル名が渡されたことを検出できないため)。
移植可能にも、この動作はPOSIXで文書化:
次の2種類のパラメータを混在させることができます。
- ファイル:プログラムに設定されているパターンと一致するように読み取る必要がある入力を含むファイルのパス名。ファイルオペランドが指定されていない場合、またはファイルオペランドが「-」の場合は、標準入力を使用する必要があります。
- 割り当て:移植可能文字セットの下線またはアルファベット文字で始まるオペランド(IEEE Std 1003.1-2001、セクション6.1移植可能文字セットのデフォルト定義ボリュームの表を参照)、その後に一連の下線、数字が続きます。および「=」文字が続く移植可能な文字セットの文字は、パス名ではなく変数の割り当てを指定する必要があります。
したがって、いくつかの移植可能なオプションがあります(#1はおそらく最も邪魔になりません)。
- 「移植可能な文字セットの下線またはアルファベット文字」ではない
awk ... ./my=file
ため、これを回避するを使用してください。.
- 標準入力にファイルを配置するために使用されます
awk ... < my=file
。ただし、これは複数のファイルでは正しく機能しません。 - 一時的にファイルへのハードリンクを作成して使用してください。このようなことを行い、
ln my=file my_file
正常my_file
に使用できます。コピーは行われず、両方のファイルは同じデータとinodeメタデータでバックアップされます。使用後は、そのアノードの参照数がまだゼロより大きいため、生成されたリンクを削除しても安全です。
答え3
見積もり愚かな文書(追加の強調事項を参照):
コマンドラインの他の引数は通常、指定された順序で処理される入力ファイルとして扱われます。しかし、var = value型のパラメータはvar変数に値を割り当て、ファイルをまったく指定しません。
コマンドが停止して待つのはなぜですか?形であるからawk 'processing_script_here' my=file.txt
指定されたファイルがありません。上記の定義では、 -my=file.txt
は変数割り当てとして解釈され、ファイルが定義されていない場合はstdinを読み取ります(これらのコマンドのawkがシステムコールを待っていることもawk
明らかです。strace
read(0,'...)
この内容はにも記録されています。POSIX awkの仕様、オペランドセクション、仕事その一部)
awk '{print foo}' foo=bar /etc/passwd
/ etc / passwdの各行は値を印刷するため、変数の割り当ては明らかです。ただし、パスまたはフルパスをfoo
指定すると機能します。./foo=bar
実行strace
してawk '1' foo=bar
確認すると、cat foo=bar
これはawk固有の問題であることがわかり、execveはファイル名を渡された引数として表示するため、この場合、シェルは環境変数の割り当てとは何の関係もありません。
awk '...script...' foo=bar
さらに、環境変数の割り当てはコマンドの前に適用する必要があるため、シェルは環境変数を生成しません。バラよりPOSIX シェル構文規則, ポイント 7. さらに、これは次のように確認できます。awk '{print ENVIRON["foo"]}' foo=bar /etc/passwd