在我的bash腳本中,有很多變量,我必須做些什麼才能將它們保存到文件中。 我的問題是如何列出我的腳本聲明的所有變量,並得到這樣的名單:如何列出在bash腳本中聲明的變量?
VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi
在我的bash腳本中,有很多變量,我必須做些什麼才能將它們保存到文件中。 我的問題是如何列出我的腳本聲明的所有變量,並得到這樣的名單:如何列出在bash腳本中聲明的變量?
VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi
set
將輸出變量,遺憾的是它也將輸出功能定義爲好。
幸運的是POSIX模式只能輸出變量:
(set -o posix ; set) | less
管道到less
,或重定向到您想要的選項。
所以在短短的腳本時聲明的變量:
(set -o posix ; set) >/tmp/variables.before
source script
(set -o posix ; set) >/tmp/variables.after
diff /tmp/variables.before /tmp/variables.after
rm /tmp/variables.before /tmp/variables.after
(或者至少一些基於該:-))
如果你能後置處理,(前面已經提到)您可能只需在腳本的開頭和結尾放置一個set
調用(每個調用一個不同的文件),然後對這兩個文件執行diff操作。意識到這仍然會包含一些噪音。
你也可以用編程方式做到這一點。要將輸出限制在當前範圍內,您必須實現一個包裝到變量創建。例如
store() {
export ${1}="${*:2}"
[[ ${STORED} =~ "(^|)${1}($|)" ]] || STORED="${STORED} ${1}"
}
store VAR1 abc
store VAR2 bcd
store VAR3 cde
for i in ${STORED}; do
echo "${i}=${!i}"
done
其中產量
VAR1=abc
VAR2=bcd
VAR3=cde
嘗試使用腳本(可以稱之爲 「ls_vars」):
#!/bin/bash
set -a
env > /tmp/a
source $1
env > /tmp/b
diff /tmp/{a,b} | sed -ne 's/^> //p'
使用chmod + X吧,:
ls_vars your-script.sh > vars.files.save
這不顯示局部變量,只顯示出口變量。 – 2010-11-01 19:50:24
for i in _ {a..z} {A..Z}; do eval "echo \${[email protected]}" ; done | xargs printf "%s\n"
這必須打印所有shell變量名稱。您可以在獲取文件之前和之後獲得一個列表,就像使用「set」來區分哪些變量是新的(如其他答案中所解釋的)。但請記住,使用diff進行過濾可以過濾掉某些需要的變量,但在獲取文件之前已經存在。
在你的情況,如果你知道你的變量的名字開始與‘變量’,則可以輸出腳本,做:
for var in ${[email protected]}; do
printf "%s%q\n" "$var=" "${!var}"
done
UPDATE:對於純BASH解決方案(不使用外部命令):
for i in _ {a..z} {A..Z}; do
for var in `eval echo "\\${[email protected]}"`; do
echo $var
# you can test if $var matches some criteria and put it in the file or ignore
done
done
compgen -v
它列出了所有變量,包括本地的。 我從bash: get list of variables whose name matches a certain pattern得知它,並在my script中使用它。
不幸的是,'compgen -v'列出了本地未設置的全局變量。不知道這是一個長期存在的錯誤還是期望的行爲。 – 2015-11-16 19:35:34
從安全角度來看,無論是@ akostadinov的answer或@ JuvenXu的answer優選依賴於所述set
命令的非結構化輸出,由於以下潛在的安全漏洞:
#!/bin/bash
function doLogic()
{
local COMMAND="${1}"
if (set -o posix; set | grep -q '^PS1=')
then
echo 'Script is interactive'
else
echo 'Script is NOT interactive'
fi
}
doLogic 'hello' # Script is NOT interactive
doLogic $'\nPS1=' # Script is interactive
上述功能doLogic
用途set
檢查是否存在變量PS1
以確定腳本是否是交互式的(不必介意這是否是實現該目標的最佳方法;這僅僅是一個示例。)
然而,set
的輸出是非結構化的,這意味着包含換行符的任何變量都可能完全污染結果。
這當然是潛在的安全風險。相反,使用Bash支持間接變量名稱擴展或compgen -v
。
嘗試這種情況:set | egrep "^\w+="
(帶或不帶| less
管道)
第一提出的解決方案,(set -o posix ; set) | less
,工作原理,但有一個缺點:它發送的控制代碼給所述終端,因此它們不正確顯示。因此,舉例來說,如果有(可能)一個IFS=$' \t\n'
變量,我們可以看到:
IFS='
'
...相反。
我的egrep
解決方案正確顯示此(最終其他類似的)。
我可能已經被盜the answer前一陣子......作爲FUNC反正稍有不同:
##
# usage source bin/nps-bash-util-funcs
# doEchoVars
doEchoVars(){
# if the tmp dir does not exist
test -z ${tmp_dir} && \
export tmp_dir="$(cd "$(dirname $0)/../../.."; pwd)""/dat/log/.tmp.$$" && \
mkdir -p "$tmp_dir" && \
(set -o posix ; set)| sort >"$tmp_dir/.vars.before"
(set -o posix ; set) | sort >"$tmp_dir/.vars.after"
cmd="$(comm -3 $tmp_dir/.vars.before $tmp_dir/.vars.after | perl -ne 's#\s+##g;print "\n $_ "')"
echo -e "$cmd"
}
基於上面的一些答案,這個工作對我來說:
before=$(set -o posix; set | sort);
源文件:
comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq)
這裏是如此mething類似@GinkgoFr答案,但沒有和@Tino或@DejayClayton, 發現的問題比@ DouglasLeeder的聰明set -o posix
位更穩健:
+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }
不同的是,該解決方案的第一個非後停止變量報告,例如第一個功能set
順便說一句:「Tino」問題已解決。儘管POSIX已關閉,並且功能由set
, 報告,但該解決方案的sed ...
部分僅允許通過可變報告(例如VAR=VALUE
行)。 特別是,A2
確實不是虛假地把它變成輸出。
+ function a() { echo $'\nA2=B'; }; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999
和:在「DejayClayton」問題得到解決(在變量值的嵌入式換行符做不破壞輸出 - 每個VAR=VALUE
得到一個輸出線):
+ A1=$'111\nA2=222'; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999
注:該解決方案由@DouglasLeeder提供的「DejayClayton」問題(嵌入換行符的值)。 下面,A1
是錯誤的,A2
根本不應該顯示。
$ A1=$'111\nA2=222'; A0=000; A9=999; (set -o posix; set) | grep '^A[0-9]='
A0=000
A1='111
A2=222'
A9=999
最後:我不認爲bash
的版本很重要,但它可能。我做了我的測試/在這一個發展:
$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)
後腳本:鑑於一些在OP對方答覆,我留下< 100%肯定set
總是轉換值內換行到\n
,這個解決方案依靠避免「DejayClayton」問題。也許這是一種現代行爲?還是編譯時間的變化?或者set -o
或shopt
選項設置?如果你知道這樣的變化,請添加評論...
我在發佈時進行了編輯。用'-o posix'調用好的差異將只包含變量。 – ezpz 2009-08-20 10:50:44
不使用臨時文件:'VARS =「\'set -o posix; set \'」;源腳本; SCRIPT_VARS =「\'grep -vFe」$ VARS「<<<」$(set -o posix; set)「| grep -v^VARS = \'」;未設置VARS;'。這也會輸出儲存在現成格式中的變量。該列表將包含腳本更改的變量(取決於這是否合意) – 2011-08-15 22:12:26
不幸的是,posix模式也會輸出不可修改的變量,因此您無法「輸出」它的輸出並將它們全部讀回。 – 2013-12-26 21:20:56