Bashで環境以外のすべての変数を一覧表示するには?

Bashで環境以外のすべての変数を一覧表示するには?

echoBash 3.2.52では、環境ではないすべての変数(すべての独自の宣言変数)が必要です。

すべての変数を印刷するこのコマンドは、私が理解できない出力を提供し、私の考えでは、私がすでにset -x && clear -r作業しているパターンと衝突します。

diff -U 1 <(set -o posix ; set |cut -d= -f1) <(
    exec bash -ic 'set -o posix ; set' | cut -d= -f1)  |
        grep '^[-][^-]'                                |
        cut -d- -f2                                    |
        grep -vE '^(COLUMNS|HISTFILESIZE|HISTSIZE|LINES|PIPESTATUS)$'

echoそのようなリストを取得するにはprintf(または他の「より簡単な」)作業が必要です。
このバージョンのBashで可能であれば、どのように達成できますか?

答え1

GNU Parallel Includeenv_parallelセクションには、env_parallelサポートされているシェルのすべての変数がリストされています。

このコードの場合はbash次のようになります。

_names_of_VARIABLES() {
    compgen -A variable
}
_bodies_of_VARIABLES() {
    typeset -p "$@"
}

したがって、すべての変数が与えられたら、ユーザーがどの変数を設定したかを調べる必要があります。私たちできるこれは特定のバージョンのすべての変数をハードコードすることによって行われますが、将来のバージョン(ユーザーまたは将来のバージョン?)でより多くの変数が設定される可能性があるため、bashこれは将来の証拠ではありません。bash$BASH_MYVARbash

したがって、env_parallelクリーンな環境を定義し、env_parallel --sessionその中で実行する必要があります。これは$PARALLEL_IGNORED_NAMES、以前に定義された名前をリストして設定されます(上記のコードを使用)。

後でユーザーが変数を設定した環境で実行してみると、クリーン環境と現在の環境の違いが簡単にわかります。

env_parallel --sessionセッションごとにきちんとした環境を定義することは可能ですが、セッション全体で使用できる参照環境が必要な場合は、変数のリストをファイルに保存できます。だから:

# In clean envronment
compgen -A variable > ~/.clean-env-vars

# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars

たとえば、

#!/bin/bash

# In clean envronment
compgen -A variable > ~/.clean-env-vars

myvar=4
yourvar=3

# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars

# This prints:
# myvar
# yourvar
# PIPESTATUS (which is set when running a pipe)

答え2

これをあなたの~/.bashrc

pre () {
    set -o posix;set > /tmp/tmp-original-envs
}

post () {
    set -o posix;set > /tmp/tmp-new-envs
    diff /tmp/tmp-original-envs /tmp/tmp-new-envs | grep -v BASH_LINENO | grep -v FUNCNAME | grep '>'
}

preその後、修正の前後にpost実行してください。

例:

[localhost]$ pre
[localhost]$ test=new
[localhost]$ post
> test=new
[localhost]$ 

答え3

必要に応じて簡単な解決策は次のとおりです。

  1. 変更する前に、set > tmp現在の変数を使用または保存してください。set > /tmp/current
  2. アプリケーションを修正/実行しますか?
  3. diff -u <(cat tmp) <(set)またはで変更されたコンテンツの抽出
diff -u <(cat tmp) <(set) | tail -n +3 | grep -v PIPESTATUS | grep -v "_=" | grep -E "^\+"

どこ:

tail -n +3:diff コマンドの最初の行から不要な行を削除します。

grep -v PIPESTATUS | grep -v "_=": 不要な変数の削除

grep -E "^\+":希望/必要な変更のみを表示

選択する:

diff -u <(set -o posix; set) <(bash -lc 'set -o posix; set') | grep -E "^\+"

メモ:

スクリプトでexec開始されたプロセスを完全に置き換えると、達成しようとしている作業が妨げられる可能性があることに注意してください。

答え4

不器用なbash専用ソリューション:

(setn(){
   set | sed '/^{/,/^}/d;/=/!d;/^BASH[A-Z_]*=\|^PPID=\|^SHLVL=\|^PIPESTATUS=\|^HISTSIZE=\|^HISTFILESIZE=\|^_[a-z_]*=/d' | sort
}
export -f setn
comm -23 <(setn) <("$BASH" -ic setn))

また、他の変数をフィルタリングする必要があるかもしれませんsed(またはパターンをより制限的に作成する必要があるかもしれません)。あるいは、などのプログラム可能な完成として定義された変数は除外するBASH..必要があります。これはより制限的です。 /_[a-z_]*=/_backup_glob_xspecs

bash型に興味深い文字を含む変数値が印刷されるため、$'...'これを処理する必要があります。

foo='
bar
baz
'
...
foo=$'\nbar\nbaz\n'

bashシェル変数は envvar では生成されません。名前改行文字が含まれているので、このようなトリックでこのハッキングを復号する方法はありません。

関連情報