zshの関数呼び出しのコンテキスト:bash `caller`と同じ

zshの関数呼び出しのコンテキスト:bash `caller`と同じ

Bashでは、次のように書くことができます。

caller 0

そして受け取った訪問者状況別:

  • 電話番号
  • 機能
  • スクリプト名

これはデバッグに非常に便利です。一方:

yelp () { caller 0; }

yelpその後、どのコード行に到達したかを確認するために書くことができます。

caller 0次のように実装できますbash

echo "${BASH_LINENO[0]} ${FUNCNAME[1]} ${BASH_SOURCE[1]"

caller 0で同じ出力をどのように取得できますかzsh

答え1

内臓はないようです。注文する同じですが、これら4つの変数のいくつかの組み合わせzsh/パラメータモジュール以下を使用できます。

funcfiletrace

EVAL_LINENOこの配列には、現在の関数、ソースファイル、または(設定されている場合)コマンドが呼び出された場所の絶対行番号とそのファイル名が含まれます eval。この配列は長funcsourcetraceさと長さは同じですfunctracefuncsourcetrace、行とファイルが定義点ではなく呼び出し点である点が異なり、functraceすべての値が関数の開始に相対的なものではなく、ファイルの絶対行番号である点が異なります。

funcsourcetrace

この配列には、現在実行中の関数、ソースファイル、および(設定されている場合)コマンドを定義するポイントのファイル名と行番号が含まれていますEVAL_LINENO。行番号は、""または""で始まる行です。自動ロードされた関数の場合、行番号は0として報告されます。各要素の形式は次のとおりです。evalfunction namename ()filename:lineno

デフォルトのzsh形式(ファイルに関数の本文のみが表示されます)のファイルから自動的にロードされる関数または組み込み関数、または「」によってsource実行されたファイルの場合、トレース情報が表示されます。定義されています。関数をロードすると、ソースファイル名は絶対パスで解決され、それ以外の場合はそのパスが解決されます。.filename:0

ほとんどのユーザーは配列の情報に興味があります funcfiletrace

funcstack

配列には、関数名、ソースファイル、および( EVAL_LINENO設定されている場合)evalコマンドが含まれます。現在実行中です。最初の要素は、このパラメーターを使用する関数の名前です。

標準シェル配列をzsh_eval_context使用して、各深度で実行されるシェル構成のタイプを決定できます。ただし、順序が反対であるため、最後の項目は最新のものであり、より詳細な項目です(たとえば、最上位の項目を含む)。メインシェルコードを対話的に実行するか、スクリプトで実行する場合$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

答え2

に基づいてムルの答え、両方で機能する次の機能を実装しました{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

関連情報