bash 如何在bash中列出脚本中声明的变量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1305237/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 18:26:06  来源:igfitidea点击:

How to list variables declared in script in bash?

bashvariables

提问by lauriys

In my script in bash, there are lot of variables, and I have to make something to save them to file. My question is how to list all variables declared in my script and get list like this:

在我的 bash 脚本中,有很多变量,我必须做一些事情才能将它们保存到文件中。我的问题是如何列出在我的脚本中声明的所有变量并获得如下列表:

VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi

回答by Douglas Leeder

setwill output the variables, unfortunately it will also output the functions defines as well.

set将输出变量,不幸的是它也会输出定义的函数。

Luckily POSIX mode only outputs the variables:

幸运的是 POSIX 模式只输出变量:

( set -o posix ; set ) | less

Piping to less, or redirect to where you want the options.

管道到less,或重定向到您想要选项的位置。

So to get the variables declared in just the script:

因此,要获取仅在脚本中声明的变量:

( 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

(Or at least something based on that :-) )

(或者至少是基于此的东西:-))

回答by Juven Xu

compgen -v

It lists all variables including local ones. I learned it from Get list of variables whose name matches a certain pattern, and used it in my script.

它列出了所有变量,包括本地变量。我从获取名称与特定模式匹配的变量列表中学到了它,并在我的脚本中使用了它。

回答by akostadinov

for i in _ {a..z} {A..Z}; do eval "echo ${!$i@}" ; done | xargs printf "%s\n"

This must print all shell variables names. You can get a list before and after sourcing your file just like with "set" to diff which variables are new (as explained in the other answers). But keep in mind such filtering with diff can filter out some variables that you need but were present before sourcing your file.

这必须打印所有 shell 变量名称。您可以在获取文件之前和之后获得一个列表,就像使用“set”来区分哪些变量是新的一样(如其他答案中所述)。但请记住,使用 diff 进行此类过滤可以过滤掉一些您需要但在获取文件之前存在的变量。

In your case, if you know your variables' names start with "VARIABLE", then you can source your script and do:

在您的情况下,如果您知道变量的名称以“VARIABLE”开头,那么您可以获取脚本并执行以下操作:

for var in ${!VARIABLE@}; do
   printf "%s%q\n" "$var=" "${!var}"
done

UPDATE:For pure BASH solution (no external commands used):

更新:对于纯 BASH 解决方案(不使用外部命令):

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

回答by Cesar Roque

Based on some of the above answers, this worked for me:

基于上述一些答案,这对我有用:

before=$(set -o posix; set | sort);

source file:

源文件

comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq) 

回答by ezpz

If you can post-process, (as already mentioned) you might just place a setcall at the beginning and end of your script (each to a different file) and do a diff on the two files. Realize that this will still contain some noise.

如果您可以进行后期处理(如前所述),您可能只需set在脚本的开头和结尾处调用(每个都指向不同的文件)并对两个文件进行比较。意识到这仍然会包含一些噪音。

You can also do this programatically. To limit the output to just your current scope, you would have to implement a wrapper to variable creation. For example

您也可以以编程方式执行此操作。要将输出限制在您当前的范围内,您必须实现一个包装器来创建变量。例如

store() {
    export ="${*:2}"
    [[ ${STORED} =~ "(^| )($| )" ]] || STORED="${STORED} "
}

store VAR1 abc
store VAR2 bcd
store VAR3 cde

for i in ${STORED}; do
    echo "${i}=${!i}"
done

Which yields

哪个产量

VAR1=abc
VAR2=bcd
VAR3=cde

回答by Stevel

Here's something similar to the @GinkgoFr answer, but without the problems identified by @Tino or @DejayClayton, and is more robust than @DouglasLeeder's clever set -o posixbit:

这是类似于@GinkgoFr 的答案,但没有@Tino 或@DejayClayton 发现的问题,并且比@DouglasLeeder 的聪明set -o posix点更强大:

+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }

The difference is that this solution STOPS after the first non-variable report, e.g. the first function reported by set

不同的是,这个解决方案在第一个非变量报告后停止,例如第一个函数报告 set

BTW: The "Tino" problem is solved. Even though POSIX is turned off and functions are reported by set, the sed ...portion of the solution only allows variable reports through (e.g. VAR=VALUElines). In particular, the A2does notspuriously make it into the output.

顺便说一句:“Tino”问题解决了。即使 POSIX 已关闭并且函数由 报告setsed ...解决方案的部分也只允许通过(例如VAR=VALUE行)报告变量。特别是,A2不会虚假地进入输出。

+ function a() { echo $'\nA2=B'; }; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999

AND: The "DejayClayton" problem is solved (embedded newlines in variable values do notdisrupt the output - each VAR=VALUEget a single output line):

AND:“DejayClayton”问题已解决(变量值中嵌入的换行符不会中断输出 - 每个都VAR=VALUE得到一个输出行):

+ A1=$'111\nA2=222'; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999

NOTE: The solution provided by @DouglasLeeder suffers from the "DejayClayton" problem (values with embedded newlines). Below, the A1is wrong and A2should not show at all.

注意:@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

FINALLY: I don't think the version of bashmatters, but it might. I did my testing / developing on this one:

最后:我认为版本bash不重要,但它可能。我对此进行了测试/开发:

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)

POST-SCRIPT: Given some of the other responses to the OP, I'm left < 100% sure that setalwaysconverts newlines within the value to \n, which this solution relies upon to avoid the "DejayClayton" problem. Perhaps that's a modern behavior? Or a compile-time variation? Or a set -oor shoptoption setting? If youknow of such variations, please add a comment...

POST-SCRIPT:鉴于对 OP 的一些其他响应,我 <100% 确定set始终将值中的换行符转换为\n,该解决方案依赖于避免“DejayClayton”问题。也许这是现代行为?还是编译时变体?或者一个set -oshopt选项设置?如果知道此类变化,请添加评论...

回答by Akash

The printenvcommand:

printenv命令:

printenvprints all environment variablesalong with their values.

printenv打印所有environment variables的值。

Good Luck...

祝你好运...

回答by grm34

Simple way to do this is to use bash strict modeby setting system environment variables before running your script and to use diff to only sort the ones of your script :

执行此操作的简单方法是通过在运行脚本之前设置系统环境变量来使用bash 严格模式,并使用 diff 仅对脚本进行排序:

# Add this line at the top of your script :
set > /tmp/old_vars.log

# Add this line at the end of your script :
set > /tmp/new_vars.log

# Alternatively you can remove unwanted variables with grep (e.g., passwords) :
set | grep -v "PASSWORD1=\|PASSWORD2=\|PASSWORD3=" > /tmp/new_vars.log

# Now you can compare to sort variables of your script :
diff /tmp/old_vars.log /tmp/new_vars.log | grep "^>" > /tmp/script_vars.log

You can now retrieve variables of your script in /tmp/script_vars.log. Or at least something based on that!

您现在可以在 /tmp/script_vars.log 中检索脚本的变量。或者至少是基于此的东西!

回答by Chen Levy

Try using a script (lets call it "ls_vars"):

尝试使用脚本(我们称之为“ls_vars”):

  #!/bin/bash
  set -a
  env > /tmp/a
  source 
  env > /tmp/b
  diff /tmp/{a,b} | sed -ne 's/^> //p'

chmod +x it, and:

chmod +x 它,并且:

  ls_vars your-script.sh > vars.files.save

回答by Dejay Clayton

From a security perspective, either @akostadinov's answeror @JuvenXu's answeris preferable to relying upon the unstructured output of the setcommand, due to the following potential security flaw:

从安全角度来看,由于以下潜在的安全漏洞,@akostadinov 的答案或 @JuvenXu 的答案都优于依赖set命令的非结构化输出:

#!/bin/bash

function doLogic()
{
    local COMMAND=""
    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

The above function doLogicuses setto check for the presence of variable PS1to determine if the script is interactive or not (never mind if this is the best way to accomplish that goal; this is just an example.)

上面的函数doLogic用于set检查变量是否存在PS1以确定脚本是否是交互式的(不管这是否是实现该目标的最佳方式;这只是一个示例。)

However, the output of setis unstructured, which means that any variable that contains a newline can totally contaminate the results.

但是, 的输出set是非结构化的,这意味着任何包含换行符的变量都可能完全污染结果。

This, of course, is a potential security risk. Instead, use either Bash's support for indirect variable name expansion, or compgen -v.

这当然是一个潜在的安全风险。相反,使用 Bash 对间接变量名称扩展的支持,或compgen -v.