2013-05-27 32 views
10

是否可以重寫shell函數並保留對原始函數的引用?重寫shell函數,保留對原始函數的引用

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

這樣做的輸出應該是:

wrapper 
original 

這可能在一個半便攜式的方式?理由:我試圖用通過將它們的調用記錄到日誌文件中的shell函數替換它的一部分來測試我的程序。只要我只打包命令和內建函數,並且只要我不介意不加區分的日誌記錄,這就可以正常工作。現在我想通過在每個測試中記錄有趣的內容來使測試套件更易於維護。

所以我們可以說我的方案包括

f 
g 
h 

其中fgh都是外殼的功能,我想追蹤的只是g執行。

+0

你想可以做,但不是很便攜的。 –

回答

3

許多shell(zsh,ksh,bash至少)支持typeset -f f轉儲內容f()。 使用此選項可將當前定義保存到文件;然後,根據需要定義f()。通過獲取使用typeset創建的文件來恢復f()。

如果你稍微修改轉儲功能(重命名f()_f()第一線;有點棘手當f()是遞歸或打電話給你以同樣的方式frobbed等功能),你可能可以得到這個產生輸出你想要的。

+0

另一個這樣的命令:'declare -f f'不知道哪個更便攜... – anishsane

+0

'typeset'和'declare'都不是POSIX(2013年第8期)。 – Jens

+0

@Jens:你的意思是第7期TC1(2013年版)。第8期尚未發佈。 :) –

4

延斯的答案是正確的。只需添加下面的代碼以獲得完整性。

您可以簡單地使用它,如下:

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

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

我曾在這裏用同樣的邏輯:https://stackoverflow.com/a/15758880/793796

+0

對於與eval的想法+1。 – Jens

+1

+1。我也使用這種技術[這裏](http://askubuntu.com/questions/73262/how-do-i-teach-bash-in-ubuntu-some-curse-words/73282#73282) –

+0

@glennjackman:我喜歡alias_function的想法:) – anishsane