下面是從我的答案What platform independent way to find directory of shell executable in shell script?摘錄其中,本身完全回答你的問題除了小寫的一部分,這在我看來,已經正式地址在這裏的其他答案許多次。
什麼是我的唯一答案是,當我試圖把它寫的其他問題,我遇到了你確切的問題 - 我怎麼了函數的結果存儲在一個變量?好吧,你可以看到,有一些幫助,我想出了一個非常簡單,非常強大的解決方案:
我可以通過功能的排序信使變量和反引用任何明確的使用所產生的函數的參數中的$1
根據需要命名爲eval
,並且在函數例程完成時,我使用eval
和反斜槓引用技巧爲我的信使變量賦予我想要的值,而無需知道它的名稱。
在充分披露,儘管這是解決我的問題,這是任何手段我的解決方案不。我以前曾經有幾次去過那裏,但他的一些描述雖然可能很精彩,但還是有些超出我的聯盟,所以我認爲如果在前一段中包含我自己的版本, 。雖然當然,一旦我明白了,理解起來很簡單,因爲特別是這一點,我不得不長時間思考,弄清楚它是如何工作的。無論如何,你可以在Rich's sh tricks處找到這個以及更多,我也在自己的答案的摘錄下摘錄了他的頁面的相關部分。
... 摘錄: ...
雖然沒有嚴格的POSIX的是,realpath是2012年以來一個GNU核心應用。全面披露:在我注意到它在info coreutils
TOC中並且立即想到[鏈接的]問題之前從未聽說過,但是使用以下函數作爲證明應該可靠(很快POSIXLY?),並且我希望能夠有效地提供它來電者有絕對貨源$0
:
% _abs_0() {
> o1="${1%%/*}"; ${o1:="${1}"}; ${o1:=`realpath "${1}"`}; eval "$1=\${o1}";
> }
% _abs_0 ${abs0:="${0}"} ; printf %s\\n "${abs0}"
/no/more/dots/in/your/path2.sh
編輯:這可能是值得強調的是這個解決方案使用POSIX parameter expansion首先檢查是否路徑實際需要擴大,並試圖這樣做之前解決的。這應該通過信使可變返回一個絕對來源$0
(與顯着的例外,它會保留symlinks
)爲有效因爲我能想象它可以做的路線是否已經是絕對的。 ...
(小修改:在文檔中找到realpath
之前,我已經至少縮減了我的版本的[版本下方]不依賴於時間領域,因爲它在不第一ps
命令],但是,公平的警告,測試一些後,我不太相信ps
在其命令路徑擴展容量)
在另一方面完全可靠,你可以這樣做:
ps ww -fp $$ | grep -Eo '/[^:]*'"${0#*/}"
eval "abs0=${`ps ww -fp $$ | grep -Eo ' /'`#?}"
... 而從Rich's sh tricks: ...
從一個shell函數返回一個字符串
正如從命令替換上述缺陷可以看出,stdout是不是一個好途徑shell函數將字符串返回給它們的調用者,除非輸出格式爲尾隨換行符不重要。當然,這種做法對於處理任意字符串的函數是不可接受的。那麼,可以做些什麼?
試試這個:
func() {
body here
eval "$1=\${foo}"
}
當然${foo}
中可以通過任何一種替代的替代。這裏的關鍵技巧是評估線和轉義的使用。當eval的參數由主命令解析器構造時,「$1」
被展開。但「${foo}」
在此階段未擴展,因爲「$」
已被引用。相反,它在eval評估其參數時展開。如果還不清楚爲什麼這很重要,請考慮以下怎麼會不好:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=$foo"
但當然,下面的版本是完全安全的:
foo='hello ; rm -rf /'
dest=bar
eval "$dest=\$foo"
注意的是,在最初的例子,「$1」
是用於允許調用者傳遞目標變量名稱作爲函數的參數。如果您的函數需要使用shift命令,例如將其餘參數作爲「[email protected]」
來處理,那麼在函數的開頭將「$1」
的值保存在一個臨時變量中可能會很有用。
謝謝!很棒。不幸的是,我的鍵盤沒有正確的刻度:(幸運的是,我能夠複製並粘貼您的代碼在我的腳本中。 – DeltaIV
@DeltaIV好聽的!我想你總是可以輸入ALT-96來獲得它:-) – Benj
使用'$(pwd)'代替反引號。它們更容易嵌套,比反引號更明顯。另外,你的鍵盤上有這些鍵:) – chepner