2013-05-27 4 views
10

Ist es möglich, eine Shell-Funktion zu überschreiben und einen Verweis auf den ursprünglichen zu behalten?Überschreiben Sie eine Shell-Funktion, behalten Sie einen Verweis auf das Original

f() { echo original; } 
f() { echo wrapper; ...; } 
f 

Der Ausgang dieses sollte sein:

wrapper 
original 

Ist das möglich in einem halb tragbare Art und Weise?

Begründung: Ich versuche mein Programm zu testen, indem ich Teile davon durch Shell-Funktionen ersetze, die ihre Aufrufe in einer Protokolldatei aufzeichnen. Das funktioniert gut, solange ich nur Kommandos und Built-Ins umschließe, und solange es mir nichts ausmacht, wahllos zu loggen. Jetzt möchte ich die Test-Suite wartbarer machen, indem ich nur das interessante Stück in jedem Test aufnehme.

Also lassen Sie uns sagen, dass mein Programm von

f 
g 
h 

besteht, wo f, g, h alle Shell-Funktionen sind, und ich möchte die Ausführung von nur g verfolgen.

+0

was Sie getan werden kann, aber nicht sehr portabel. –

Antwort

3

Viele Shells (zsh, ksh, bash zumindest) unterstützen typeset -f f, um den Inhalt von f() auszugeben. Verwenden Sie dies, um die aktuelle Definition in einer Datei zu speichern; Definieren Sie dann f(), wie Sie möchten. Stellen Sie f() wieder her, indem Sie die mit typeset erstellte Datei einlesen.

Wenn Sie leicht die abgeladen Funktion (Umbenennung f()-_f() in der ersten Zeile, ein bisschen schwieriger, wenn f() rekursiv oder andere Funktionen aufruft Sie auf die gleiche Art und Weise frobbed) ändern, werden Sie wahrscheinlich dies zu produzieren bekommen Ausgabe, die Sie wünschen.

+0

Ein anderer solcher Befehl: 'declare -f f' Nicht sicher, welcher portabler ist ... – anishsane

+0

Weder' setset' noch 'declare' sind POSIX (Ausgabe 8, 2013). – Jens

+0

@Jens: Sie meinen Ausgabe 7 TC1 (Ausgabe 2013). Ausgabe 8 wurde noch nicht veröffentlicht. :) –

4

Die Antwort von Jens ist korrekt. Fügen Sie einfach den folgenden Code zur Vollständigkeit hinzu.

Sie können es einfach wie unten verwenden:

eval "`declare -f f | sed '1s/.*/_&/'`" #backup old f to _f 

f(){ 
    echo wrapper 
    _f # pass "[email protected]" to it if required. 
} 

ich hier gleiche Logik verwendet hatte: https://stackoverflow.com/a/15758880/793796

+0

+1 für die Idee mit Eval. – Jens

+1

+1. Ich habe auch diese Technik [hier] (http://askubuntu.com/questions/73262/how-do-i-teach-bash-in-ubuntu-some-curse-words/73282#73282) –

+0

@glennjackman: I gefiel die Idee von alias_function :) – anishsane

Verwandte Themen