3

関数が定義されているかどうかを確認する適切な方法を求めています。POSIX 準拠の方法。

__function_defined() {
    FUNC_NAME=$1
    d=$(declare -f $FUNCNAME)

    if [ "${DISTRO_NAME_L}" = "centos" ]; then
        if typeset -f $FUNC_NAME &>/dev/null ; then
            echo " * INFO: Found function $FUNC_NAME"
            return 0
        fi

    # Try POSIXLY_CORRECT or not
    elif test -n "${POSIXLY_CORRECT+yes}"; then
        if typeset -f ${FUNC_NAME} >/dev/null 2>&1 ; then
            echo " * INFO: Found function $FUNC_NAME"
            return 0
        fi
    else
        # Arch linux seems to fall here
        if $( type ${FUNC_NAME}  >/dev/null 2>&1 ) ; then
            echo " * INFO: Found function $FUNC_NAME"
            return 0
        fi
    echo " * INFO: $FUNC_NAME not found...."
    return 1
}

上記のすべては、debian のcheckbashismsスクリプトによると、bash'isms と見なされます。

スクリプトをgrepしようとしても大丈夫ではありません。例えば:

    if [ "$(grep $FUNC_NAME $(dirname $0)/$(basename $0))x" != "x" ]; then
        # This is really ugly and counter producing but it was, so far, the
        # only way we could have a POSIX compliant method to find if a function
        # is defined within this script.
        echo " * INFO: Found function $FUNC_NAME"
        return 0
    fi

スクリプトは次のようにも機能するはずなので、機能しません。

wget --no-check-certificate -O - http://URL_TO_SCRIPT | sudo sh

では、これを行うための適切な POSIX 準拠の方法は何ですか?

プレーンshでお願いします。bashもkshも他のシェルもありません。プレーンshだけです。ああ、実際に関数を実行しようとせずに:)

出来ますか?

POSIX準拠のソリューションを見つけました:

if [ "$(command -v $FUNC_NAME)x" != "x" ]; then
    echo " * INFO: Found function $FUNC_NAME"
    return 0
fi

今の質問、より良い解決策はありますか?

4

4 に答える 4

2

POSIX準拠の方法を見つけました

if [ "$(command -v $FUNC_NAME)x" != "x" ]; then
    echo " * INFO: Found function $FUNC_NAME"
    return 0
fi

今の質問、より良い解決策はありますか?

于 2013-01-22T20:30:49.653 に答える
1

この回答はPOSIXではないため、受け入れられた回答と競合しませんが、特定のシェルに何かが必要な場合はFWIW / TDILになる可能性があります。

zshできますtest "$(whence -w name)" = 'name: function'

bashできますtest "$(type -t name)" = 'function'

の詳細bash:

function fn () {
  echo 'my function'
}

if test "$(type -t fn)" = 'function'; then
  echo 'fn is a function'
else
  echo 'fn is not a function'
fi

if test "$(type -t missing-fn)" = 'function'; then
  echo 'missing-fn is a function'
else
  echo 'missing-fn is not a function'
fi

helpプロンプトに入力してからhelp typeとを入力すると、bash bultins の詳細を確認できますhelp test

type -t namenameまた、ビルトイン、ファイル、または示されている関数など、あらゆる種類のものかどうかもわかります。

変数または関数が存在することのみを気にする場合は、次を使用できます。

if test -v name; then
  echo "name is present: $name"
else
  echo "name is missing"
fi
于 2021-09-02T20:05:39.970 に答える
1

以下は POSIX 準拠であり、おそらくどこでも動作するはずです。

checkfunc() {
   case "$(type "$1" 2>/dev/null | head -n1)" in
   *" function"|*" function from zsh") return 0; ;;
   esac
   return 1
}
# Tested with:
# My shell is bash
script="$(declare -f checkfunc)"'
if checkfunc checkfunc; then :; else echo $0:error:not function; exit 1; fi
if checkfunc ls; then echo $0:error:executable; exit 1; fi
if checkfunc type; then echo $0:error:builtin; exit 1; fi
if checkfunc does-not-exists; then echo $0:error:not-exists; exit 1; fi
'
docker run --rm bash bash -c "$script"
docker run --rm alpine ash -c "$script"
docker run --rm ubuntu dash -c "$script"
docker run --rm alpine ash -c 'apk add mksh >/dev/null && mksh -c "$1"' - "$script"
docker run --rm alpine ash -c 'apk add zsh >/dev/null && zsh -c "$1"' - "$script"

私が言うことができれば、SVR4 のソースを入手してパッチを適用することもできるkshので、現在の GCC でコンパイルでき、そこでもテストしtype<xxx> is a functionash.

zshが出力されるので、特別<func> is a shell function from zshに扱うことにしました。from zsh

于 2021-09-02T21:48:50.597 に答える