如何在 bash 中仅打印定义的变量(shell 和/或环境变量)

如何在 bash 中仅打印定义的变量(shell 和/或环境变量)

bash 内置命令set,如果不带参数调用,将打印所有 shell 和环境变量,以及所有定义的函数。这使得输出无法供人类使用并且难以使用grep

如何使 bash 内置命令set仅打印变量而不打印函数?

是否还有其他命令只打印 shell 变量而不打印函数?

注意:bash 区分 shell 变量和环境变量。看这里bash中环境变量和导出环境变量的区别

答案1

“还有其他命令只打印 shell 变量而不打印函数吗?”

在 man bash 中,SHELL BUILTIN COMMANDS 部分(在 set 部分)中显示:“在 posix 模式下,仅列出 shell 变量。”

(set -o posix; set)

注意:()语法会生成一个子 shell,如果您不喜欢分叉,只需使用更详细的版本

set -o posix; set; set +o posix

答案2

以下是一些解决方法:

$ comm -3 <(declare | sort) <(declare -f | sort)

分解:

  1. declare打印每个定义的变量(导出或未导出)和函数。
  2. declare -f仅打印函数。
  3. comm -3将删除两者共有的所有行。实际上,这将删除函数,只留下变量。

仅打印未导出的变量:

$ comm -3 <(comm -3 <(declare | sort) <(declare -f | sort)) <(env | sort)

另一个解决方法:

$ declare -p

这只会打印变量,但带有一些丑陋的属性。

declare -- BASH="/bin/bash"
declare -ir BASHPID=""
declare -A BASH_ALIASES='()'
declare -a BASH_ARGC='()'
...

您可以使用... cut 来剪切属性:

$ declare -p | cut -d " " -f 3

一个缺点是 IFS 的值是解释而不是显示的。

比较:

$ comm -3 <(declare | sort) <(declare -f | sort)
...
IFS=$' \t\n'
...
$ declare -p | cut -d " " -f 3
...
IFS="
"
...

"由于该输出仅在一行中,因此很难使用该输出进行进一步处理。也许可以做一些 IFS-fu 来防止这种情况发生。


另一种解决方法是使用compgen

$ compgen -v

bash 内置函数compgen旨在用于完成脚本中。为此,compgen -v列出所有定义的变量。缺点:它仅列出变量名称,而不列出值。

这是一个也列出这些值的技巧。

$ compgen -v | while read var; do printf "%s=%q\n" "$var" "${!var}"; done

优点:它是一个纯粹的 bash 解决方案。缺点:由于 的解释,一些值被搞乱了printf。此外,管道和/或循环中的子 shell 添加了一些额外的变量。

答案3

奇怪的是,内置函数typeset有一个选项只显示函数(-f),但不只显示参数。幸运的是,typeset(或set) 显示所有函数之前的所有参数,函数和参数名称不能包含换行符或等号,并且参数值中的换行符被引用(它们显示为\n)。因此,您可以在不包含等号的第一行处停止:

set | awk -F '=' '! /^[0-9A-Z_a-z]+=/ {exit} {print $1}'

这只打印参数名称;如果您想要这些值,请更改print $1print $0.

请注意,这会打印所有参数名称(此处参数和变量同义使用),而不仅仅是环境变量(“环境变量”与“导出的参数”同义)。

另请注意,这假设不存在名称与 bash 对参数名称的约束不匹配的环境变量。这些变量不能在 bash 内部创建,但可以在 bash 启动时从环境继承:

env 'foo ()
{
  =oops' bash

答案4

只需使用命令即可env。它不打印函数。

相关内容