Shellから関数の長さを取得する

Shellから関数の長さを取得する

修正する:

いくつかの背景:

zsh$LINENO関数内で呼び出されると、関数内の行番号を返します。ファイルの行番号を取得し、ファイル行zsh番号と関数行番号が与えられたときにそれらを区別する方法が必要です。

zsh他の Bourne シェルと一致するようにこの動作を変更する環境変数が見つからなかったため (たとえば、常にbashファイル行番号を指定するなど)、常にファイル行のコンテキストを出力するロジックを使用して関数を作成できることを確認しようとしました。数字。だから関数の長さを決定しようとしています。

$LINENOすべての状況でファイルの行番号を取得する良い方法を知っている人がいる場合は、zshありがとうございます!


質問:

私は検索しましたこれそしてこれしかし、答えが見つからないようです。関数定義を1行で記述する移植可能な方法はありますか?(上記の「一部の背景」を参照してください.)

私の初期のアイデアは、関数の内容をキャプチャすることによってwc -l

次のテストファイルを検討してください。

テストファイル:

#! /bin/sh
#
# test_file.sh

func1() { echo 'A one-liner'; }  # With a nasty comment at the end
func2 (){
  echo "A sneaky } included"
  # Or an actual code block
  {
    echo 'hi'
    echo 'there'
  }
}

func3() { echo "I'm on a line."; }; echo 'And so am I'

func4(){ echo "But I'm a \"stand-alone\" one-liner."; }

func5() {
  echo "I'm a nice function."
  echo "And you can too!"


}

echo "Can we do this?"

私の最初の試みは、sedを使用して対応する{}ペアを一致させることでした。

試すことができる回避策:

#! /bin/sh
#
# function_length
#
# $1: string: absolute path to file
# $2: string: name of function (without ()'s)

fp=$(realpath "$1")
func_name="$2"

func_contents=$(cat "${fp}" |
  sed -E -n '
/'"${func_name}"' ?[(][)]/{
  :top
  /[}]/!{
    H
    d
  }
  /[}]/{
    x
    s/[{]//
    t next
    G
    b end
  }
  :next
  x
  b top
  :end
  p
  q
}')

echo "${func_contents}"
echo

func_len=$(echo "${func_contents}" | wc -l)

echo "Function Length: ${func_len}"

しかし、zshで実行すると

$ ./function_length ./test_file.sh func1      

func1() { echo 'A one-liner'; }  # With a nasty comment at the end

Function Length: 2
$ ./function_length ./test_file.sh func2


Function Length: 1
$ ./function_length ./test_file.sh func3

func3() { echo "I'm on a line."; }; echo 'And so am I'

Function Length: 2
$ ./function_length ./test_file.sh func4

func4(){ echo "But I'm a \"stand-alone\" one-liner."; }

Function Length: 2
$ ./function_length ./test_file.sh func5


Function Length: 1

誰もが解決策を知っていますか?ありがとうございます!

答え1

シェル関数の内容を取得する移植可能な方法はありません。一部の殻にはあり、一部にはありません。人気のシェルスプリント関数の本文を評価する以外は何もできません。

dash/src $ grep -F ndefun.body *.c
eval.c: evaltree(func->n.ndefun.body, flags & EV_TESTED);
parser.c:                               n->ndefun.body = command();

ソースコードを詳しく調べてみると、関数の「長さ」が何を意味しているかに関係なく、別のデータ構造が含まれていないことがわかります。

関数定義を印刷する方法があるシェルでは、その形式がソースコードと異なる場合があります。したがって、「長さ」は意味のある数字ではありません。

$ bash -c 'f () { echo hello; echo world; }; typeset -f f'
f () 
{ 
    echo hello;
    echo world
}
$ ksh -c 'f () { echo hello; echo world; }; typeset -f f'; echo
f() { echo hello; echo world; };
$ mksh -c 'f () { echo hello; echo world; }; typeset -f f'
f() {
        \echo hello 
        \echo world 
} 
$ zsh -c 'f () { echo hello; echo world; }; typeset -f f'
f () {
        echo hello
        echo world
}

関連情報