Comment redéfinir une fonction bash en termes d'ancienne définition?

13

Existe-t-il un moyen de redéfinir une fonction bash en fonction de son ancienne définition? Par exemple, je voudrais ajouter le bloc de code suivant au préambule de la fonction command_not_found_handle (),

# Check if $1 is instead a bash variable and print value if it is
local VAL=$(eval echo \"\$$1\")
if [ -n "$VAL" ] && [ $# -eq 1 ]; then
    echo "$1=$VAL"
    return $?
fi

Il est actuellement défini dans /etc/profile.d/PackageKit.sh et provient de scripts de démarrage bash.

De cette façon, je peux interroger la valeur d'une variable d'environnement à l'invite de commande en tapant simplement le nom de la variable (et à condition qu'aucune commande de ce nom n'existe). par exemple

user@hostname ~:$ LANG
LANG=en_AU.utf8

Je sais que je pourrais simplement copier et coller la définition actuelle et ajouter mes propres modifications ~/.bashrc, mais je cherche une manière plus élégante qui implique la réutilisation du code.

De meilleurs moyens d'atteindre mon objectif ou des améliorations / extensions de code sont également appréciés.

tmoschou
la source
Si cette question était mieux adaptée sur stackoverflow, quelqu'un peut-il la migrer, je ne sais pas comment.
tmoschou
3
Je pense que ce post sur Stack Overflow répond à votre question.
Mat
2
Au lieu de eval, vous pouvez utiliser l'indirection:local VAL=$(echo ${!1})
pause jusqu'à nouvel ordre.

Réponses:

14

Vous pouvez imprimer la définition actuelle de la fonction, puis l'inclure dans une définition de fonction à l'intérieur d'une evalclause.

current_definition=$(declare -f command_not_found_handle)
current_definition=${current_definition#*\{}
current_definition=${current_definition%\}}
prefix_to_add=$(cat <<'EOF'
  # insert code here (no special quoting required)
EOF
)
suffix_to_add=$(cat <<'EOF'
  # insert code here (no special quoting required)
EOF
)
eval "command_not_found_handle () {
  $prefix_to_add
  $current_definition
  $suffix_to_add
}"

Une autre approche, que je trouve plus claire, consiste à définir la fonction d'origine sous un nouveau nom, et à l'appeler à partir de votre définition. Cela ne fonctionne que si vous n'avez pas besoin d'agir sur les variables locales de la définition d'origine.

eval "original_$(declare -f command_not_found_handle)"
command_not_found_handle () {
  
  original_command_not_found_handle
  
}
Gilles 'SO- arrête d'être méchant'
la source
1
À la vôtre, il ne m'est jamais venu à l'esprit d'utiliser ici des documents, aucun devis spécial requis. Je pense que je préfère votre première méthode, facilite la visualisation de la définition complète avec declare -f, mais j'aime la façon dont vous renommez la fonction d'origine.
tmoschou
0

Merci @mat, @ dennis-williamson. Après avoir lu vos commentaires, voici ce que j'ai

eval 'command_not_found_handle () {

    local VAL=$(echo "${!1}")
    if [ -n "$VAL" ] && [ $# -eq 1 ]; then
            echo "$1=$VAL"
            return $?
    fi

    '$(declare -f command_not_found_handle |
    tail -n +3 | head -n -1)'
}'

Bien que je pense que je préfère la solution @Gilles.

tmoschou
la source