3

具有多行值的环境变量可能会混淆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=提取所有名称,因为它显示错误的名称CE

# 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/\1\n/g'
A
TERM
SHELL
USER
MAIL
PATH
PWD
LANG
PS1
SHLVL
HOME
LOGNAME
_

但是 BusyBox 的版本env 不支持flag -0。还有另一种方法吗?

4

3 回答 3

4

如果您使用的是 linux(我认为busybox 只在 linux 上运行,但我可能错了),它包含一个 NUL 分隔的环境,与给您/proc/self/environ的形式相同。env -0您可以替换env -0 |< /proc/self/environ.

sed -e ':a;N;$!ba;s/\([^=]\+\)=\([^\x00]*\)\x00/\1\n/g' < /proc/self/environ
于 2012-06-23T03:50:56.570 回答
2

这可能不是一个优雅但有效的解决方案。它首先从 的输出中提取所有可能的名称env,然后使用 shell 的扩展来验证它们中的每一个${parameter:+word}。最后它会删除重复项,因为相同的变量名可以打印在env's 输出中的多行上(作为真正的变量名和其他变量的多行值的一部分):

env | awk -F= '/[a-zA-Z_][a-zA-Z_0-9]*=/ {
        if (!system("[ -n \"${" $1 "+y}\" ]")) print $1 }' | sort | uniq

PS:该| sort | uniq部分也可以在awk.

于 2012-06-23T03:08:22.763 回答
1

如果您的环境变量包含空值,这将中断。但这也会破坏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 '\0' '\n' | cut -d '=' -f 1
于 2019-01-09T23:46:25.863 回答