awk 'processing_script_here' my=file.txt
停止して無期限に待機しているように見えます...
ここで何が起こっているのでしょうか?
awk 'processing_script_here' my=file.txt
停止して無期限に待機しているように見えます...
ここで何が起こっているのでしょうか?
回答:
クリスは言う、フォームの引数は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
orや=bar
orのような引数./foo=bar
は、入力ファイル名として扱われ、最初の引数の残りが=
有効な変数名ではないため、割り当てとしては扱われません。実装とロケールにStéphane=Chazelas.txt
応じて、引数のような場合とそうでない場合がawk
あります。
そのため、awkでは次の使用をお勧めします。
awk '...' ./*.txt
の代わりに
awk '...' *.txt
たとえば、txt
ファイルの名前に=
文字が含まれないことを保証できない場合に問題を回避するためです。
また、次のような引数を-vfoo=bar.txt
オプションとして扱う場合があることに注意してください:
awk -f file.awk -vfoo=bar.txt
(も適用されawk '{code}' -vfoo=bar.txt
てawk
busyboxのバージョンから前1.28.0に、参照対応するバグレポートを)。
繰り返しになりますが、これを./*.txt
回避することで回避できます(./
プレフィックスを使用すると、代わりに標準入力を意味するものとして理解されるファイルが呼び出さ-
れます)。awk
それも理由です
#! /usr/bin/awk -f
シバンは実際には機能しません。一方で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
引数のリストが常に入力ファイルであるシェバンス(ステートメントARGV
内でそのリストを自由に編集できることに注意してBEGIN
ください)。
次のように使用することもできます。
gawk -e '...awk code here...' -E /dev/null *.txt
-E
空のスクリプト(/dev/null
)を使用するのは、*.txt
それらに=
文字が含まれている場合でも、後でそれらが常に入力ファイルとして扱われるようにするためです。
../foo
、/path/to/foo
および異なるエンコーディングであるパス) -その場合にはsubstr(FILENAME,3)
十分な、またはそれのないであろうユーザーが基本的にファイル名を知っているワンショットスクリプトです。この場合、おそらく=
どちらも含む
./
問題だとは思わないが、出力にファイル名を含める./
必要がある場合など、特定の条件下では望ましくない場合があり、その場合は冗長で不要である必要があるため、どういうわけかそれを取り除く必要があります。以下に少なくとも1つの例を示します。ユーザーがファイル名を知っている場合-この場合、ファイル名も知っていますが、=
それでも適切な処理の妨げになります。リード-
が邪魔をすることができます。
./
そのawk
(誤)機能を回避するためにプレフィックスを使用したいが、それからあなたは./
あなたがストリップしたいかもしれない出力でそれで終わるということです。ファイルの最初の行に特定の文字列が含まれているかどうかを確認する方法を参照してください?例として。
./
だけでなく、/
awkに引数をファイルとして解釈させるグローバル(絶対パス)でもあります。
awkのほとんどのバージョンでは、実行するプログラムの後の引数は次のいずれかです。
x=y
ファイル名はケース#2として解釈されているため、awkはまだstdinで何かを読むのを待っています(ファイル名が渡されたことを認識しないため)。
移植性があるため、この動作はPOSIXで文書化されています。
次の2種類の引数のいずれかを混在させることができます。
- file:読み込む入力を含むファイルのパス名。これは、プログラム内の一連のパターンと照合されます。ファイルオペランドが指定されていない場合、またはファイルオペランドが「-」の場合、標準入力が使用されます。
- 割り当て:ポータブル文字セットのアンダースコアまたはアルファベット文字で始まるオペランド(IEEE Std 1003.1-2001、セクション6.1、ポータブル文字セットの基本定義ボリュームの表を参照)、その後に一連のアンダースコア、数字、ポータブル文字セットのアルファベット文字とそれに続く「=」文字は、パス名ではなく変数の割り当てを指定するものとします。
そのため、移植性があるため、いくつかのオプションがあります(#1が最も邪魔にならない可能性が高い)。
awk ... ./my=file
。これは、.
「ポータブル文字セットのアンダースコアまたはアルファベット文字」ではないためです。awk ... < my=file
ます。ただし、これは複数のファイルではうまく機能しません。ln my=file my_file
から、my_file
通常どおり使用できます。コピーは実行されず、両方のファイルは同じデータとiノードのメタデータによってバックアップされます。それを使用した後、iノードへの参照の数はまだ0より大きいため、作成されたリンクを削除しても安全です。./my=file
か? 有効な変数名ではない% awk 'processing_script_here' ./my=file.txt awk: fatal: cannot open file ./my=file.txt' for reading (No such file or directory).
ため、これは移植性があるはず./my
です。したがって、そのように解析されるべきではありません。
=
前にポータブル文字セットのアンダースコアまたはアルファベット文字がある場合のみです(IEEE Std 1003.1-2001、セクション6.1、ポータブル文字セットのベース定義ボリュームの表を参照)。ポータブル文字セットからのアンダースコア、数字、およびアルファベットのシーケンスが続きます。以下のようなファイルパスはそう++foo=bar.txt
か、=foo
または./foo=bar
されているすべてのOKはそのよう.
か+
ではありません[_a-zA-Z]
。
./my=file
逐語的に渡されます。
awk '{print $1,$2}' /etc/passwd
。要点は、awkとは対照的にシェルにファイルを開かせても、シーク可能にするかどうかについては違いはありません。実際、でawk '{exit}' < /etc/passwd
、awk
最初のレコードの末尾に戻って、exit
そこにあるstdin内の位置から離れることを確認します。POSIXにはそれが必要です。/usr/xpg4/bin/awk
それは、Solaris上で行いますが、どちらgawk
もmawk
GNU / Linux上でそれを行うように見えます。
awk
そのようにして特定された位置。
gawkのドキュメントを引用するには(注意を強調してください):
コマンドラインの追加の引数は、通常、指定された順序で処理される入力ファイルとして扱われます。ただし、var = valueという形式の引数は、値valueを変数varに割り当てます。ファイルをまったく指定しません。
コマンドが停止して待機するのはなぜですか?フォームawk 'processing_script_here' my=file.txt
には上記の定義で指定されたファイルがありません - my=file.txt
変数割り当てとして解釈され、定義されたファイルがない場合awk
はstdinを読み取ります(strace
そのようなコマンドのawkがread(0,'...)
syscall で待機していることからも明らかです
これは、に記載されてPOSIXのawkの仕様オペランド部と、参照、代入)その一部を
変数の割り当ては、/ etc / passwdのすべての行にのawk '{print foo}' foo=bar /etc/passwd
値foo
が出力されることから明らかです。./foo=bar
ただし、フルパスを指定しても機能します。
実行strace
しawk '1' foo=bar
て確認するとcat foo=bar
、これはawk固有の問題であり、execveは渡された引数としてファイル名を表示するため、この場合、シェルはenv変数の割り当てとは関係ありません。
さらに、awk '...script...' foo=bar
環境変数の割り当てを有効にしてコマンドの前に置く必要があるため、シェルによる環境変数の作成は発生しません。POSIX Shell Grammar Rules、ポイント番号7を参照してください。さらに、これはawk '{print ENVIRON["foo"]}' foo=bar /etc/passwd