具有多行值的环境变量可能会混淆env
的输出:
# export A="B
> C=D
> E=F"
# env
A=B
C=D
E=F
TERM=xterm
SHELL=/bin/bash
USER=root
MAIL=/var/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/root
LANG=en_US.UTF-8
PS1=h:w$
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env
在这种情况下,我不能只使用 awk -F=
来提取所有名称,因为它C
和E
显示错误的名称:
# env | awk -F= '{print $1}'
A
C
E
TERM
SHELL
USER
MAIL
PATH
PWD
LANG
PS1
SHLVL
HOME
LOGNAME
_
然后我发现env
支持标志-0
以 0 字节而不是换行符结束每个输出行,因此使用 sed
我可以切断 bash
中的值:
# env -0 | sed -e ':a;N;$!ba;s/([^=]+)=([^x00]*)x00/1n/g'
A
TERM
SHELL
USER
MAIL
PATH
PWD
LANG
PS1
SHLVL
HOME
LOGNAME
_
但是BusyBox的env
版本不支持标志-0
。有没有其他方法可以做到这一点?
如果你使用的是linux(我以为busybox只在linux上运行,但我可能是错的),/proc/self/environ
包含一个NUL分离的环境,其形式与env -0
给你的形式相同。您可以将env -0 |
替换为 < /proc/self/environ
。
sed -e ':a;N;$!ba;s/([^=]+)=([^x00]*)x00/1n/g' < /proc/self/environ
这可能不是一个优雅但有效的解决方案。它首先从env
的输出中提取所有可能的名称,然后使用 shell 的扩展${parameter:+word}
验证每个名称。最后,它删除了重复项,因为相同的变量名可以打印在env
输出中的几行上(作为真正的变量名和其他变量的多行值的一部分):
env | awk -F= '/[a-zA-Z_][a-zA-Z_0-9]*=/ {
if (!system("[ -n "${" $1 "+y}" ]")) print $1 }' | sort | uniq
PS:| sort | uniq
部分也可以在awk
中实现。
如果您的环境变量值包含空值,这将中断。但这也会破坏POSIX的兼容性。
所以它应该有效。
。除非您希望遇到包含换行符的环境变量名称。在这种情况下,换行符在显示时将被截断。但是,我似乎无法理解如何在 busybox shell 中创建带有换行符的环境变量。无论如何,我当地的贝壳都对此犹豫不决。所以我不认为这将是一个大问题。就POSIX所说,Other characters may be permitted by an implementation; applications shall tolerate the presence of such names.
所以我认为剥离它们而不是错误是可以容忍的。
# Read our environment; it's delimited by null bytes.
# Remove newlines
# Replace null bytes with newlines
# On each line, grab everything before the first '='
cat /proc/self/environ | tr -d 'n' | tr ' ' 'n' | cut -d '=' -f 1