Bash
在管道中呼叫我的函式時未設置環境變數
我有以下遞歸函式來設置環境變數:
function par_set { PAR=$1 VAL=$2 if [ "" != "$1" ] then export ${PAR}=${VAL} echo ${PAR}=${VAL} shift shift par_set $* fi }
如果我自己呼叫它,它會設置變數並回顯到標準輸出:
$ par_set FN WORKS FN=WORKS $ echo "FN = "$FN FN = WORKS
將標準輸出重定向到文件也可以:
$ par_set REDIR WORKS > out cat out REDIR=WORKS $ echo "REDIR = "$REDIR REDIR = WORKS
但是,如果我將 stdout 傳遞給另一個命令,則不會設置變數:
$ par_set PIPE FAILS |sed -e's/FAILS/BARFS/' PIPE=BARFS $ echo "PIPE = "$PIPE PIPE =
為什麼管道會阻止函式導出變數?有沒有辦法在不使用臨時文件或命名管道的情況下解決這個問題?
解決了:
感謝 Gilles 的工作程式碼:
par_set $(echo $*|tr '=' ' ') > >(sed -e's/^/ /' >> ${LOG})
這允許這樣呼叫腳本:
$ . ./script.sh PROCESS_SUB ROCKS PIPELINES=NOGOOD $ echo $PROCESS_SUB ROCKS $ echo $PIPELINES NOGOOD $ cat log 7:20140606155622162731431:script.sh:29581:Parse Command Line parameters. Params must be in matched pairs separated by one or more '=' or ' '. PROCESS_SUB=ROCKS PIPELINES=NOGOOD
如果對完整程式碼感興趣,項目託管在 bitbucket https://bitbucket.org/adalby/monitor-bash上。
管道的每一部分(即管道的每一側)都在一個單獨的程序中執行(稱為子shell,當shell派生出一個子程序來執行部分腳本時)。在
par_set PIPE FAILS |sed -e's/FAILS/BARFS/'
中,PIPE
變數設置在執行管道左側的子程序中。這種變化不會反映在父程序中(環境變數不會在程序之間傳遞,它們只會被子程序繼承。管道的左側始終在子外殼中執行。一些 shell(ATT ksh、zsh)在父 shell 的右側執行;大多數還在子shell中執行右側。
如果您想重定向腳本的一部分的輸出並在父 shell 中執行該部分,在 ksh/bash/zsh 中,您可以使用程序替換。
par_set PROCESS SUBSTITUTION > >(sed s/ION/ED/)
使用任何 POSIX shell,您都可以將輸出重定向到命名管道。
mkfifo f <f grep NAMED= & par_set NAMED PIPE >f
哦,你缺少圍繞變數替換的引號,你的程式碼在諸如
par_set name 'value with spaces' star '*'
.export "${PAR}=${VAL}" … par_set "$@"