2012-06-22 53 views
2

具有多值的環境變量可能會混淆env的輸出:名單busybox的所有環境變量名

# 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的版本envdoes not support標誌-0的。還有另一種方法可以做到嗎?

+0

您是否願意使用其他腳本語言來完成這項工作,比如'python -c'import os;打印「」.join(os.environ中的x爲「\ n」,x爲「鍵%ENV」或「perl -le」),或者你需要限制自己一套最小的shell工具? – Celada

+0

@Celada:用Python它太容易了:)在這裏,我只能使用BusyBox。 – spatar

回答

1

這可能不是一個優雅但工作的解決方案。它首先從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中實現。

2

如果您正在使用linux(我認爲busybox只在linux上運行,但我可能是錯的),/proc/self/environ包含一個與env -0相同形式的NUL分隔環境。您可以用< /proc/self/environ替換env -0 |

sed -e ':a;N;$!ba;s/\([^=]\+\)=\([^\x00]*\)\x00/\1\n/g' < /proc/self/environ 
+0

解析'/ proc/self/environ'是一個好主意,但是你在我的例子中使用的'sed'腳本在busybox的sed實現中並不像常規GNU sed那樣工作。 sed腳本的第一部分'sed -e':a; N; $!ba''應該將所有行集合成一個([見此處](http://stackoverflow.com/questions/1251999/sed-how- can-i-replace-a-newline-n#1252191)),但是在busybox中它也用'\ n'替換所有的'\ 0'字符。在bash和busybox中試試這個命令:'echo -ne「A \ 0B」| sed -e':a; N; $!ba'| hexdump -C'。 – spatar

相關問題