mawkで独自のスクリプト名を印刷する方法は?


13

bash $0にはスクリプトの名前が含まれていますが、awkには次の内容でmyscript.awkという名前のスクリプトを作成した場合:

#!/usr/bin/awk -f
BEGIN{ print ARGV[0] }

実行すると、「awk」のみが出力されます。また、i> 0のARGV [i]は、コマンドラインのスクリプト引数にのみ使用されます。それでは、スクリプトの名前、この場合は「myscript.awk」を印刷する方法は?


私は(Ubuntuの上などデフォルト)ソリューションをすべてのgawkを必要とし、一般的なawkと仕事をしないためのmawkへのawkからタイトルを変更した、とのmawkで特に広く使用されている
cipper

mawkUbuntuのデフォルトは何だと思いますか?15.04 VMでは、デフォルトawkgawkです。mawkがインストールされている間、それはデフォルトではありません。
テルドン

1
で呼び出すとawkスクリプトになりますawk -f myscript.awk。ただし、これは問題の問題とは無関係です。
ニッパー

1
@EdMorton awkで始まるため、スクリプト#!/usr/bin/awk -fです。シェルスクリプトは#!/bin/sh(または類似の)で始まります。
バーマー

1
私はさまざまなシェルの専門家と話をしていて、それがシェルまたはawkスクリプトであるかどうかについて決定的な答えを得ようとしていますが、驚くことに#で始まるファイルの解釈 未定義であり、特定のタイプ名はありません。一部の人々はそれをシェルやawkスクリプトではなく「ハッシュバンインタープリタースクリプト」と呼んでいますが、コンセンサスはawkがまだ(シェルではなく)カーネルが最初の行を解釈してもawkスクリプトと見なされるべきであるようです最初の行も(コメントとして)解析できなければならず、を使用して実行できますawk -f file
エド・モートン

回答:


5

cygwinのbashでGNU awk 4.1.3を使用する場合:

$ cat tst.sh
#!/bin/awk -f
BEGIN { print "Executing:", ENVIRON["_"] }

$ ./tst.sh
Executing: ./tst.sh

それがどれほど移植性があるのか​​わかりません。ただし、いつものように、シェルスクリプトでシバンを使用してawkスクリプトを実行することはありません。シンプルに保ち、代わりにこれを実行してください:

$ cat tst2.sh
awk -v cmd="$0" '
BEGIN { print "Executing:", cmd }
' "$@"

$ ./tst2.sh
Executing: ./tst2.sh

その最後は、どのプラットフォームのどのシェルでも、最新のawkで動作します。


最初のものはbash、zshまたはkshでのみ機能することに注意してください。後者は、awkスクリプトではなく、シェルスクリプトに関するものです。
クオンルム

2
ありがとうございました!ENVIRON["_"]完全に機能し、外部プログラムを呼び出しません。2番目のオプションawk -v ...は、スクリプトの実行方法によって異なります。これは欲しくありません。
ニッパー

1
スクリプトを呼び出すことtst.shは誤解を招きます。これはawkスクリプトであり、シェルスクリプトではありません。BEGIN有効なシェルコマンドではありません。
バーマー

1
正しいが、移植性の問題は「ENVIRON []ポータブル」ではなく、「ENVIRON["_"]すべてのシェルからシバンを介して呼び出されるすべてのawkから印刷されたときに、呼び出しシェルスクリプトパスを生成しますか?」私はシバンからawkスクリプトを呼び出すことは決してありませんが、私は個人的に答えを気にしませんが、私はそれを言及すると思っただけです...ああ、@ cuonglmはそれがいくつかのシェルでのみサポートされていると答えた。
エド・モートン

1
良い点、@ Ed。ダッシュ(現在のコマンドではなく、前のコマンド(またはシェル自体)を返す)で失敗することを確認しました。おもしろいことに、ksh93はPIDの前にアスタリスクを付けます*12345*/tmp/test.awkARGV[0]確実に常にawkダッシュ、bash、zsh、およびksh93にあります。
アダム・カッツ

5

私はこれがgawk ドキュメントごとに可能だとは思わない:

最後に、ARGV[0](7.5組み込み変数を参照)の値はオペレーティングシステムによって異なります。awkそこに置くシステム、awkのフルパス名(など/bin/awk)を置くシステム、スクリプトの名前(アドバイス)を置くシステムがあります。の値に依存しARGV[0]てスクリプト名を指定しないでください。

linuxあなた汚いハックのようなものを使用して試すことができますとのコメントで指摘したようにステファンChazelasの実装ならば、それは可能ですawkがサポートNULバイトを:

#!/usr/bin/awk -f

BEGIN { getline t < "/proc/self/cmdline"; split(t, a, "\0"); print a[3]; }

スクリプトはそのままでは機能していないようです。「awk -f script.awk」で呼び出された場合は「k」を出力し、「./ script.awk」で呼び出された場合は「s」を出力します
cipper

@cipper:ここでで動作しgawk、(あなたの説明のように)で失敗しmawkます。面白い!

Linuxでは、awk4.0.2で動作します。とfreebsdで/proc/curpoc/cmdlineawk結果はあなたのものに似ていますが、で動作しgawkます。
タリエジン

デフォルトのubuntuでは機能しません。ポータブルなソリューションを見つけることができればうれしいです。
ニッパー

1
@taliezin:cuonglmによる答えは、名前付きのスクリプトを手動でフィードする必要があるため、解決策ではありません。これは、呼び出してawk -vNAME="myscript.awk" ./myscript.awkからスクリプト内にNAMEを出力するようなものです。解決策ではありません。
ニッパー

5

私はawk内からコマンド名を取得する直接的な方法を知りません。ただし、サブシェルを介して見つけることができます。

ガック

GNU awkとpsコマンドを使用すると、プロセスIDを使用PROCINFO["PID"]して回避策としてコマンド名を取得できます。例えば:

cmdname.awk

#!/usr/bin/gawk -f

BEGIN {
  ("ps -p " PROCINFO["pid"] " -o comm=") | getline CMDNAME
  print CMDNAME
}

鷹と鷹

同じアプローチを使用できますがawk$PPID特別なシェル変数(親のPID)からのPIDを導出します。

cmdname.awk

#!/usr/bin/mawk -f

BEGIN { 
  ("ps -p $PPID -o comm=") | getline CMDNAME
  print CMDNAME
}

テスト中

次のようなスクリプトを実行します。

./cmdname.awk

両方の場合の出力:

cmdname.awk

エラーが発生しました:/ bin / sh:1:-o:not found
cipper

@cipper:これはGNU awkでのみ動作します。行方不明のシェバン行を追加しました。
トール

gawkマニュアルから: POSIXによると、「式| 式に '$'以外の括弧なしの演算子が含まれる場合、getline 'はあいまいです。たとえば、' "echo" "date" | 連結演算子が括弧で囲まれていないため、getline 'はあいまいです。'( "echo" "date")|と書く必要があります| プログラムをすべてのawk実装に移植可能にする場合は、getlineを使用します。
ニッパー

1
必要なgawk場合は、gawkソリューションではなくawkソリューションです。@cipperは彼の願い「ポータブルソリューション」を質問に追加すべきだと思います。

1
@Thor:cuonglmによる答えは、名前を付けてスクリプトを手動でフィードする必要があるため、解決策ではありません。これは、呼び出してawk -vNAME="myscript.awk" ./myscript.awkからスクリプト内にNAMEを出力するようなものです。解決策ではありません。
ニッパー

4

POSIXの場合awk

#!/usr/bin/awk -f

BEGIN {
    print ENVIRON["AWKSCRIPT"]
}

次に:

AWKSCRIPT=test.awk ./test.awk
test.awk

4
スクリプトの名前を手動で入力します。これは自己印刷の方法ではありません
-cipper

@cipper:それは、私が想像できる最も簡単で移植可能な方法です。
クオンルム

2
これは、スクリプトを呼び出しawk -vNAME="myscript.awk" ./myscript.awkて変数NAMEを出力するようなものです。解決策ではありません。
ニッパー

@cipper:に言及しmawkた場合、それが唯一の方法です。そしてまた、使用しては、ENVIRON使用するのと同じではない-vNAME="myscript.awk"とき以来、mawk中にエスケープシーケンスを拡大していきますNAME
cuonglm

4

GNU awkを使用する

GNU awkユーザーガイドを確認する-7.5.2情報伝える組み込み変数

PROCINFO#

この配列の要素は、実行中のawkプログラムに関する情報へのアクセスを提供します。次の要素(アルファベット順)が使用可能であることが保証されています。

PROCINFO ["pid"]

現在のプロセスのプロセスID。

つまり、実行時にプログラムのPIDを知ることができます。次に、system()このPID を使用してプロセスを探すために使用する問題です。

#!/usr/bin/gawk -f
BEGIN{ pid=PROCINFO["pid"]
       system("ps -ef | awk '$2==" pid " {print $NF}'")
}

ps -ef2列目にPIDを表示するを使用します。executiongが実行されawk -f <script>、他のパラメーターがないと仮定すると、行の最後のフィールドに必要な情報が含まれていると想定できます。

いくつかのパラメーターがある場合、行を異なる方法で解析する必要があります-または、もっと良いことに、ps興味のある列だけを印刷するオプションをいくつか使用します。

テスト

$ awk -f a.awk 
a.awk
$ cp a.awk hello.awk
$ awk -f hello.awk 
hello.awk

また、GNU awkユーザーガイドの別の章では、ARGVを使用する方法ではないことを示しています。

1.1.4実行可能awkプログラム

最後に、ARGV [0](組み込み変数を参照)の値は、オペレーティングシステムによって異なります。一部のシステムは「awk」をそこに配置し、一部はawkのフルパス名(/ bin / awkなど)を配置し、一部のスクリプトはスクリプトの名前(「アドバイス」)を配置します。(dc)スクリプト名を提供するためにARGV [0]の値に依存しないでください。


残念ながらPROCINFOはgawkの機能であり、一般的なawkではありません。例えば、それは(Ubuntuのデフォルトでインストールされている)のmawkに使用できません
cipper

私は知っています...なぜ質問に[gawk]のタグを付けたのですか?
フェドルキ

あなたが正しい。質問を投稿したとき、mawkとgawkのこれらすべての違いについては知りませんでした。タグはmawkに変更されました。
ニッパー

@cipper good:)私は実際にそれをテストしmawkて動作させることができなかったのでgawk、Ubuntu にインストールして動作しました。したがって、回避策を使用することができますgawk:D
fedorqui

1
@terdonは、gawkUbuntu(またはmawkデフォルトのawk実装である少なくともいくつかのUbuntuバージョン)にはデフォルトでインストールされません。IIRC、Debianにもインストールする必要がありました。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.