web-dev-qa-db-ja.com

posix Shell:環境変数名のリストを出力します(値なし)

複数の実装で機能するposix互換の方法で、現在定義されている環境変数なしの値のリストを出力するにはどうすればよいですか?

一部の実装(mksh、freebsd/bin/sh)では、exportを単独で使用するだけで十分です。

$ export
FOO2
FOO

ただし、他の一部の実装(bash、zsh、dash)では、exportも値を示します。たとえば、bashの場合:

$ export
export FOO2='as  df\
  asdk=fja:\
asd=fa\
asdf'
export FOO='sjfkasjfd  kjasdf:\
   asdkj=fkajdsf:\
       :askjfkajsf=asdfkj:\
   safdkj'
$ printenv | sed -n l
FOO2=as\tdf\$
  asdk=fja:\$
asd=fa\$
asdf$
FOO=sjfkasjfd  kjasdf:\$
   asdkj=fkajdsf:\$
\t:askjfkajsf=asdfkj:\$
   safdkj$

envprintenvなどの他のオプションには、値なしで変数名のみを出力するオプションがありません。少なくとも、私が試したlinuxおよびfreebsdプラットフォームではそうではありません。

Awk/sed/etcへのパイピング。または、パラメータ拡張テクニック(例:${foo%%=*})は許容されますが、複数の行にまたがり、=と値の空白(上記の例を参照)。

特定のシェル実装に固有の回答は興味深いですが、私は主に実装間で互換性のあるものを探しています。

11
Juan

これはawkではかなり簡単です。

awk 'BEGIN{for(v in ENVIRON) print v}'

ただし、一部のawk実装は独自の環境変数を追加することに注意してください(たとえば、GNU awkはAWKPATHAWKLIBPATHENVIRONに追加します)。

環境変数の名前に改行が含まれている場合、出力はあいまいになります。これは非常に珍しいことですが、技術的には可能です。純粋なshソリューションは難しいでしょう。あなたの最善の策はexport -pから始めることですが、純粋なshでそれをマッサージすることは困難です。 sedを使用してexport -pの出力をマッサージし、次にevalを使用してシェルに引用されたものを削除させることができます。 bashとzshは非標準のプレフィックスを出力します。

report () { echo "${1%%=*}"; };
eval "$(export -p | sed "s/^export /report /;
                         s/^declare -x /report /;
                         s/typeset -x /report /")"

シェルによっては、export -pはシェルで無効な名前の変数を表示する場合と表示しない場合があります。表示されない場合は、名前を適切に引用符で囲んでいる場合といない場合があります。たとえば、ダッシュ、mksh、およびzshは、名前に改行が含まれる変数を省略し、BusyBoxダッシュおよびksh93は、それらを生で出力し、bashは、値なしで生で出力します。信頼できない入力から防御する必要がある場合は、純粋なPOSIXソリューションに依存せず、export -pの出力から派生したものに対してevalを絶対に呼び出さないでください。

私は単純なものが好きです。これはPOSIXシステムで機能します。

printenv | sed 's;=.*;;' | sort
HOME
HOSTNAME
PATH
PWD
SHLVL
TERM
0
todd_dsm