Zoeken…


Invoering

Eerst en vooral: weet wat je doet! Ten tweede, als je eval zou moeten vermijden, als het gebruik ervan schonere code oplevert, ga je gang.

Eval gebruiken

Overweeg bijvoorbeeld het volgende dat de inhoud van $@ instelt op de inhoud van een gegeven variabele:

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

Deze code gaat vaak gepaard met getopt of getopts om $@ te stellen op de uitvoer van de bovengenoemde optieparsers, maar u kunt het ook gebruiken om een eenvoudige pop functie te maken die stil en direct op variabelen kan werken zonder het resultaat op te slaan om de originele variabele:

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
}

Eval gebruiken met Getopt

Hoewel eval misschien niet nodig is voor een pop achtige functie, is het echter wel vereist wanneer je getopt :

Overweeg de volgende functie die -h als optie accepteert:

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 "$@"
}

Zonder eval set -- "$argv" genereert -h -- plaats van de gewenste (-h --) en komt vervolgens in een oneindige lus omdat -h -- niet overeenkomt -- of -h .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow