サーチ…


前書き

まず第一に、あなたがやっていることを知ってください!第二に、 eval使用を避けるべきですが、より洗練されたコードを使用する場合は、先に進んでください。

評価を使用する

たとえば、 $@の内容を指定された変数の内容に設定する次のことを考えてみましょう。

a=(1 2 3)
eval set -- "${a[@]}"

このコードでは、前述のオプションパーサーの出力に$@を設定するためにgetoptまたはgetoptsが付いていることがよくありますが、これを使用して、結果を格納せずに静かに直接変数を操作できる単純なpop関数を作成することもできます元の変数:

isnum()
{
    # is argument an integer?
    local re='^[0-9]+$'
    if [[ -n $1 ]]; then
        [[ $1 =~ $re ]] && return 0
        return 1
    else
        return 2
    fi
}

isvar()
{
    if isnum "$1"; then
        return 1
    fi
    local arr="$(eval eval -- echo -n "\$$1")"
    if [[ -n ${arr[@]} ]]; then
        return 0
    fi
    return 1
}

pop()
{
    if [[ -z $@ ]]; then
        return 1
    fi

    local var=
    local isvar=0
    local arr=()
    
    if isvar "$1"; then # let's check to see if this is a variable or just a bare array
        var="$1"
        isvar=1
        arr=($(eval eval -- echo -n "\${$1[@]}")) # if it is a var, get its contents
    else
        arr=($@)
    fi
    
    # we need to reverse the contents of $@ so that we can shift
    # the last element into nothingness
    arr=($(awk <<<"${arr[@]}" '{ for (i=NF; i>1; --i) printf("%s ",$i); print $1; }'

    # set $@ to ${arr[@]} so that we can run shift against it.
    eval set -- "${arr[@]}"
    
    shift # remove the last element
    
    # put the array back to its original order
    arr=($(awk <<<"$@" '{ for (i=NF; i>1; --i) printf("%s ",$i); print $1; }'
    
    # echo the contents for the benefit of users and for bare arrays
    echo "${arr[@]}"

    if ((isvar)); then
        # set the contents of the original var to the new modified array
        eval -- "$var=(${arr[@]})" 
    fi
}

GetoptでEvalを使う

pop様の関数ではevalは必要ないかもしれませんが、 getoptを使うときはいつでも必要です:

-hをオプションとして受け入れる次の関数を考えてみましょう。

f()
{
    local __me__="${FUNCNAME[0]}"
    local argv="$(getopt -o 'h' -n $__me__ -- "$@")"

    eval set -- "$argv"
    
    while :; do
        case "$1" in
            -h)
              echo "LOLOLOLOL"
              return 0
              ;;
            --)
              shift
              break
              ;;
    done
    
    echo "$@"
}

eval set -- "$argv"なしset -- "$argv"は、目的の(-h --)代わりに-h --生成し、その後-h ----または-h一致しないため無限ループに入ります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow