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


11

複数の実装で機能する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$

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

awk / sed / etcへのパイピング。または、パラメーター展開手法(例:)を使用してリストをトリミングする${foo%%=*}こともできますが、行をまたがる可能性が=あり、値に空白が含まれる可能性がある値を処理する必要があります(上記の例を参照)。

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


2
何かを解析する場合export -pは、POSIXで指定されている出力を使用して、シェルでの入力にも適した出力を生成します。
クサラナンダ

シェルへの入力には何も必要ありません。環境変数の名前が欲しいだけです。したがって、余分な残骸(たとえば、各行の先頭にある「エクスポート」という単語)は、とにかく削除する必要があります。なぜexport -pこれを使用したいのですか?
フアン

1
export -pすべてのPOSIXシェルで一貫性のある出力が得られるため、使用したいと思います。
クサラナンダ

シェル全体で一貫したソリューションである変数名のみを出力するソリューションが必要です。 export -p最初の要件に適合しません-値なしで変数名のみを出力します。
ファン、

IFあなたが何かを解析しようとしている、の出力で行きますexport -p。一般的なケースでは、値がのような変数である場合に備えて、適切な引用構文解析も行う必要があるため、その構文解析は記述しませんhello\nexport var=value。すべてのPOSIXシェルで一貫した出力を提供する他のいくつかのコマンドの1つはですがenv、その出力はビットが不足しているため解析が困難export =です。
クサラナンダ

回答:


9

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

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

しかし、いくつかのawk処理系では、独自の環境変数を追加します(たとえば、GNU awkの追加用心AWKPATHAWKLIBPATHしますENVIRON)。

環境変数の名前に改行が含まれている場合、出力はあいまいになります。これは非常に珍しいことですが、技術的には可能です。純粋な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 dashおよびksh93は、それらを未加工で印刷し、bashは、値なしで未加工で印刷します。信頼できない入力から防御する必要がある場合は、純粋なPOSIXソリューションに依存しないでください。またeval、の出力から派生したものを絶対に呼び出さないでくださいexport -p


複数行の値を持つsed(1)を使用すると、本当に「簡単」であるかどうかわかりません。それを確認したいと思います。しかし、awk(1)メソッドに感謝します。これはこれまでで最も移植性の高い方法だと思います(ただし、これexitは必要ではないと思います)。
フアン

を取得した場合FOO<newline>BAR、それがFOO<newline>BAR環境変数(export -pほとんどのシェルでは表示されない、を参照env $'FOO\nBAR=test' awk 'BEGIN{for (v in ENVIRON) print v}')であるか、FOOBAR環境変数の両方であるかがわからないことに注意してください。
ステファンChazelas

なお、GNU awk独自ののS組の環境変数(AWKPATHAWKLIBPATH私のシステム上)
ステファンChazelas

@StéphaneChazelas-re:var nameに埋め込まれた改行-同意-シェルコードでそれを防御するのは難しい。Re:AWKPATHとAWKLIBPATHの汚染、私はその陰湿な挿入にも気づきました。それはbsd awkではなく、gnu awkです。
フアン

0

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

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

5
export AAA=$'multi\nBBB=line'
roaima

@todd_dsm-これは、複数行にまたがる値を持つ環境変数では失敗します(たとえば、TERMCAP-ときどき、screen(1)セッション、IIRCでこれが表示されます)。したがって、この回答は元の質問で説明されている要件を満たしていません。私もシンプルが好きですが、これは一般的には機能しません。
フアン

元の投稿で編集した一口は、bashにとって興味深いものでしたcompgen -e。それは私のポータブルスクリプト(たとえば、bashが利用できない場合)には役立ちませんが、興味深いものです。
フアン

好奇心旺盛ですが、なぜボーン(posix)シェルに制限するのですか?posix準拠であることは素晴らしいことですが、その追求では多くの機能が失われます。移植可能で、bashとのposix準拠ではない場合があります。これはGNUファミリーの一部です。
todd_dsm

dashdebianで使用すると、上記のコマンドで同じ結果printenv | sed 's;*=.;;' | sortが得られるか、値を取得するように変更されます。変数をエクスポートして、yo上記の最初のコメントに割り当てました。期待どおりに複数行で印刷されました。何が発生しているかはわかりませんが、出力が切り捨てられるべきではありません。シェルでコマンドを実行します。それが出力するものは何でも、それがどのように機能するかです。切り捨てを期待しないでください。次に、TERMCAP / screen / iircのコンテキスト内。同じでなければなりません。出力が一致しない場合は、これらのプログラムのいずれかに問題がある可能性があります。
todd_dsm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.