如何列出在bash脚本中声明的variables?
在我的bash脚本中,有很多variables,我必须做些什么来保存它们。 我的问题是如何列出在我的脚本中声明的所有variables,并得到像这样的列表:
VARIABLE1=abc VARIABLE2=def VARIABLE3=ghi
set
将输出variables,不幸的是它也会输出函数定义。
幸运的是POSIX模式只输出variables:
( set -o posix ; set ) | less
pipe道less
,或redirect到你想要的选项。
所以要获取在脚本中声明的variables:
( 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
(或者至less基于这个:-))
compgen -v
它列出了所有variables,包括本地variables。 我从bash中学到了:获取名称与特定模式匹配的variables列表 ,并在脚本中使用它。
for i in _ {a..z} {A..Z}; do eval "echo \${!$i@}" ; done | xargs printf "%s\n"
这必须打印所有的shellvariables名称。 您可以在获取文件之前和之后获得一个列表,就像使用“set”来区分哪些variables是新的(如其他答案所述)。 但是请记住,使用diff进行过滤可以过滤掉一些您需要但在提供文件之前已经存在的variables。
在你的情况下,如果你知道你的variables的名字是以“VARIABLE”开始的,那么你可以获得你的脚本的源代码并执行:
for var in ${!VARIABLE@}; do printf "%s%q\n" "$var=" "${!var}" done
更新:对于纯粹的BASH解决scheme(不使用外部命令):
for i in _ {a..z} {A..Z}; do for var in `eval echo "\\${!$i@}"`; do echo $var # you can test if $var matches some criteria and put it in the file or ignore done done
如果可以后处理(如前所述),则可以在脚本的开始和结尾处(每个脚本分别对应不同的文件)进行一次set
调用,然后对这两个文件执行差异操作。 意识到这仍然会包含一些噪音。
你也可以通过编程来完成。 为了将输出限制在当前范围内,必须实现一个包装到variables的创build。 例如
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
根据上面的一些答案,这对我有效:
before=$(set -o posix; set | sort);
源文件 :
comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq)
尝试使用脚本(让我们称之为“ls_vars”):
#!/bin/bash set -a env > /tmp/a source $1 env > /tmp/b diff /tmp/{a,b} | sed -ne 's/^> //p'
chmod + x it,和:
ls_vars your-script.sh > vars.files.save
从安全angular度来看,@ akostadinov的回答或者@ JuvenXu的回答要比依赖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
来检查variablesPS1
的存在,以确定脚本是否是交互式的(不要介意这是否是实现这个目标的最好方法;这只是一个例子)。
但是, set
的输出是非结构化的,这意味着任何包含换行符的variables都可能完全污染结果。
这当然是一个潜在的安全风险。 相反,使用Bash支持间接variables名称扩展或compgen -v
。
试试这个: set | egrep "^\w+="
set | egrep "^\w+="
(有或没有pipe道)
首先提出的解决scheme, ( set -o posix ; set ) | less
( set -o posix ; set ) | less
,工作但有一个缺点:它将控制代码传送到terminal,所以它们不能正确显示。 例如,如果有(可能) IFS=$' \t\n'
variables,我们可以看到:
IFS=' '
…代替。
我的egrep
解决scheme正确地显示了这个(以及其他类似的) 。
我以前可能已经把答案偷走了 ……无论如何,它们的function稍有不同:
## # 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" }