Bashでは、私は書くことができます:
caller 0
caller コンテキストの受信:
これはデバッグに非常に役立ちます。与えられた:
Yelp () { caller 0; }
次に、Yelp
と書いて、到達しているコード行を確認します。
bash
にcaller 0
を次のように実装できます:
echo "${BASH_LINENO[0]} ${FUNCNAME[1]} ${BASH_SOURCE[1]"
zsh
のcaller 0
と同じ出力を取得するにはどうすればよいですか?
組み込みのコマンドに相当するものはないと思いますが、 zsh/Parameterモジュール からのこれら4つの変数のいくつかの組み合わせは利用される:
_funcfiletrace
_この配列には、現在の関数、ソースファイル、または(_
EVAL_LINENO
_が設定されている場合)eval
コマンドが呼び出されたポイントの絶対行番号と対応するファイル名が含まれます。配列の長さはfuncsourcetrace
およびfunctrace
と同じですが、funcsourcetrace
とは異なり、行とファイルは呼び出しのポイントであり、定義のポイントではありません。functrace
とは異なります。すべての値は、関数の開始からの相対位置ではなく、ファイル内の絶対行番号です。_funcsourcetrace
_この配列には、関数、ソースファイル、および(_
EVAL_LINENO
_が設定されている場合)現在実行されているeval
コマンドが定義されたポイントのファイル名と行番号が含まれます。行番号は、「_function name
_」または「name ()
」が開始された行です。自動ロードされた関数の場合、行番号はゼロとして報告されます。各要素の形式は_filename:lineno
_です。関数の本体のみがファイルで発生するネイティブzsh形式のファイルから自動ロードされる関数、または
source
または '_.
_'ビルトインによって実行されたファイルの場合、トレースファイル全体が定義であるため、情報は_filename:0
_として表示されます。ソースファイル名は、関数のロード時に絶対パスに解決されるか、そうでなければ解決されます。代わりに、ほとんどのユーザーは
funcfiletrace
配列の情報に関心があります。_funcstack
_この配列には、関数の名前、ソースファイル、および(_
EVAL_LINENO
_が設定されている場合)eval
コマンドが含まれます。現在実行中です。最初の要素は、パラメーターを使用する関数の名前です。標準のShell配列_
zsh_eval_context
_を使用して、各深度で実行されるShell構成のタイプを決定できます。ただし、これは逆の順序で行われ、最新のアイテムが最後になり、より詳細になります。トップレベルのエントリを含む例。対話的にまたはスクリプトから実行されるメインのシェルコード。これは_$funcstack
_にはありません。_functrace
_この配列には、現在実行されている関数に対応する呼び出し元の名前と行番号が含まれています。各要素の形式は_
name:lineno
_です。ソースファイルの呼び出し元も表示されます。呼び出し元は、source
または ‘_.
_’コマンドが実行されたポイントです。
比較:
_foo.bash
_:
_#! /bin/bash
Yelp() {
caller 0
}
foo () {
Yelp
}
foo
_
_foo.zsh
_:
_#! /bin/zsh
Yelp() {
print -l -- $funcfiletrace - $funcsourcetrace - $funcstack - $functrace
}
foo () {
Yelp
}
foo
_
結果:
_$ bash foo.bash
7 foo foo.bash
$ zsh foo.zsh
foo.zsh:7
foo.zsh:10
-
foo.zsh:2
foo.zsh:6
-
Yelp
foo
-
foo:1
foo.zsh:10
_
したがって、対応する値は_${funcfiletrace[1]}
_および_${funcstack[-1]}
_にあります。 Yelp
を次のように変更:
_Yelp() {
print -- $funcfiletrace[1] $funcstack[-1]
}
_
出力は次のとおりです。
_foo.zsh:7 foo
_
これはbashにかなり近い
_7 foo foo.bash
_
muru's answer に基づいて、両方で機能する次の関数を実装しました{ba,z}sh
:
$ cat Yelp
#!/bin/zsh
# Say the file, line number and optional message for debugging
# Inspired by bash's `caller` builtin
# Thanks to https://unix.stackexchange.com/a/453153/143394
function Yelp () {
# shellcheck disable=SC2154 # undeclared zsh variables in bash
if [[ $BASH_VERSION ]]; then
local file=${BASH_SOURCE[1]} func=${FUNCNAME[1]} line=${BASH_LINENO[0]}
else # zsh
emulate -L zsh # because we may be sourced by zsh `emulate bash -c`
# $funcfiletrace has format: file:line
local file=${funcfiletrace[1]%:*} line=${funcfiletrace[1]##*:}
local func=${funcstack[2]}
[[ $func =~ / ]] && func=source # $func may be filename. Use bash behaviour
fi
echo "${file##*/}:$func:$line $*" > /dev/tty
}
foo () { Yelp; }
Yelp
foo
出力は次のとおりです。
$ ./Yelp
yelp::20
Yelp:foo:19