Jak ponownie zdefiniować funkcję bash pod względem starej definicji?

13

Czy jest jakiś sposób, aby ponownie zdefiniować funkcję bash pod względem jej starej definicji? Na przykład chciałbym dodać następujący blok kodu do preambuły funkcji 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

Jest on obecnie zdefiniowany w /etc/profile.d/PackageKit.sh i pochodzi ze skryptów startowych bash.

W ten sposób mogę zapytać o wartość zmiennej środowiskowej w wierszu polecenia, po prostu wpisując nazwę zmiennej (i pod warunkiem, że takie polecenie o tej nazwie nie istnieje). na przykład

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

Wiem, że mogłem po prostu skopiować i wkleić bieżącą definicję i dodać własne zmiany ~/.bashrc, ale szukam bardziej eleganckiego sposobu, który wymaga ponownego użycia kodu.

Doceniane są także lepsze sposoby osiągnięcia mojego celu lub ulepszeń / rozszerzeń kodu.

tmoschou
źródło
Jeśli to pytanie byłoby bardziej odpowiednie w przypadku przepełnienia stosu, czy ktoś może je migrować, nie wiem jak.
tmoschou
3
Myślę, że ten post na przepełnieniu stosu odpowiada na twoje pytanie.
Mat.
2
Zamiast tego evalmożesz użyć pośredniej:local VAL=$(echo ${!1})
Wstrzymano do odwołania.

Odpowiedzi:

14

Możesz wydrukować bieżącą definicję funkcji, a następnie zawrzeć ją w definicji funkcji w evalklauzuli.

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

Innym podejściem, które wydaje mi się jaśniejsze, jest zdefiniowanie oryginalnej funkcji pod nową nazwą i wywołanie jej z twojej definicji. Działa to tylko wtedy, gdy nie musisz oddziaływać na lokalne zmienne oryginalnej definicji.

eval "original_$(declare -f command_not_found_handle)"
command_not_found_handle () {
  
  original_command_not_found_handle
  
}
Gilles „SO- przestań być zły”
źródło
1
Pozdrawiam, nigdy nie przyszło mi do głowy korzystać z dokumentów tutaj, bez specjalnego cytowania. Myślę, że wolę twoją pierwszą metodę, ułatwia przeglądanie całej definicji declare -f, ale podoba mi się sposób, w jaki zmieniasz nazwę oryginalnego func.
tmoschou
0

Dzięki @mat, @ dennis-williamson. Po przeczytaniu twoich komentarzy to właśnie otrzymałem

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)'
}'

Chociaż myślę, że wolę rozwiązanie @Gilles.

tmoschou
źródło