回答:
set
変数を出力しますが、残念ながら、定義された関数も出力します。
幸いなことに、POSIXモードは変数のみを出力します。
( set -o posix ; set ) | less
へのパイピングless
、またはオプションが必要な場所へのリダイレクト。
スクリプトで宣言された変数を取得するには、次のようにします。
( set -o posix ; set ) >/tmp/variables.before
source script
( set -o posix ; set ) >/tmp/variables.after
diff /tmp/variables.before /tmp/variables.after
rm /tmp/variables.before /tmp/variables.after
(または少なくともそれに基づいたもの:-))
VARS="`set -o posix ; set`"; source script; SCRIPT_VARS="`grep -vFe "$VARS" <<<"$(set -o posix ; set)" | grep -v ^VARS=`"; unset VARS;
。これにより、変数がすぐに保存できる形式で出力されます。リストには、スクリプトによって変更された変数が含まれます(これが望ましいかどうかによって異なります)
source
場合は、の出力を使用して再作成できるようにする必要がありdeclare -p
ます。
before=$(set -o posix; set); dosomestuff; diff <(echo "$before") <(set -o posix; set)
compgen -v
ローカル変数を含むすべての変数をリストします。名前が特定のパターンに一致する変数のGetリストからそれを学び、スクリプトで使用しました。
compgen -v
ローカルで設定解除されたグローバル変数もリストします。それが長年のバグなのか、それとも望ましい動作なのかはわかりません。
for i in _ {a..z} {A..Z}; do eval "echo \${!$i@}" ; done | xargs printf "%s\n"
これは、すべてのシェル変数名を出力する必要があります。"他の回答で説明されているように"どの変数が新しいかを比較する "set"と同じように、ファイルをソーシングする前後にリストを取得できます。ただし、diffを使用したこのようなフィルタリングでは、ファイルを調達する前に存在していた必要な変数を除外できることに注意してください。
あなたの場合、変数の名前が「VARIABLE」で始まることがわかっている場合は、スクリプトをソースとして実行できます。
for var in ${!VARIABLE@}; do
printf "%s%q\n" "$var=" "${!var}"
done
更新:純粋なBASHソリューションの場合(外部コマンドは使用されません):
for i in _ {a..z} {A..Z}; do
for var in `eval echo "\\${!$i@}"`; do
echo $var
# you can test if $var matches some criteria and put it in the file or ignore
done
done
eval "printf '%q\n' $(printf ' "${!%s@}"' _ {a..z} {A..Z})"
(すでに述べたように)後処理が可能な場合set
は、スクリプトの最初と最後に(それぞれ別のファイルに)呼び出しを行い、2つのファイルを比較することができます。これにはまだノイズが含まれていることを認識してください。
プログラムでこれを行うこともできます。出力を現在のスコープのみに制限するには、変数の作成にラッパーを実装する必要があります。例えば
store() {
export ${1}="${*:2}"
[[ ${STORED} =~ "(^| )${1}($| )" ]] || STORED="${STORED} ${1}"
}
store VAR1 abc
store VAR2 bcd
store VAR3 cde
for i in ${STORED}; do
echo "${i}=${!i}"
done
収量
VAR1=abc
VAR2=bcd
VAR3=cde
これは@GinkgoFrの回答に似ていますが、@ Tinoまたは@DejayClaytonによって識別される問題がなく、@ DouglasLeederの巧妙なset -o posix
ビットよりも堅牢です。
+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }
違いは、このソリューションは最初の非変数レポートの後に停止することです。たとえば、 set
ところで:「ティノ」の問題は解決されました。POSIXがオフになっていて、関数がによって報告されているset
場合でもsed ...
、ソリューションの一部では、変数の報告(例:VAR=VALUE
行)のみが許可されます。特に、は誤って出力に入れA2
ません。
+ function a() { echo $'\nA2=B'; }; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999
AND:「DejayClayton」問題が解決されます(変数値に埋め込まれた改行は出力を中断しません -それぞれVAR=VALUE
が単一の出力行を取得します):
+ A1=$'111\nA2=222'; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999
注:@DouglasLeederによって提供されるソリューションは、「DejayClayton」問題(改行が埋め込まれた値)の影響を受けます。以下はA1
が間違っているため、A2
まったく表示されません。
$ A1=$'111\nA2=222'; A0=000; A9=999; (set -o posix; set) | grep '^A[0-9]='
A0=000
A1='111
A2=222'
A9=999
最後に:私はbash
問題のバージョンを考えていませんが、そうかもしれません。私はこれをテスト/開発しました:
$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)
POST-SCRIPT:OPへの他のいくつかの応答を考えると、値内の改行をset
常にに変換することは100%未満\n
であり、「DejayClayton」の問題を回避するためにこのソリューションはこれに依存しています。おそらくそれは現代的な行動でしょうか?またはコンパイル時のバリエーション?またはA set -o
またはshopt
オプション設定?そのようなバリエーションを知っている場合は、コメントを追加してください...
セキュリティの観点からは、どちらか@ akostadinovの答えや@ JuvenXuの答えはの構造化されていない出力に依存することが好ましいset
ため、以下の潜在的なセキュリティ上の欠陥に、コマンドを実行します。
#!/bin/bash
function doLogic()
{
local COMMAND="${1}"
if ( set -o posix; set | grep -q '^PS1=' )
then
echo 'Script is interactive'
else
echo 'Script is NOT interactive'
fi
}
doLogic 'hello' # Script is NOT interactive
doLogic $'\nPS1=' # Script is interactive
上記の関数doLogic
はset
、変数の存在を確認するために使用しますPS1
、スクリプトがインタラクティブかどうかを判断するため(これがその目的を達成するための最良の方法であるかどうかは気にしないでください。これは単なる例です。)
ただし、の出力 set
は構造化されていません。つまり、改行を含む変数は結果を完全に汚染する可能性があります。
もちろん、これは潜在的なセキュリティリスクです。代わりに、Bashの間接変数名展開のサポート、またはを使用してくださいcompgen -v
。
これを試してください:(配管のset | egrep "^\w+="
有無にかかわらず| less
)
最初に提案されたソリューションは( set -o posix ; set ) | less
機能しますが、欠点があります。制御コードが端末に送信されるため、適切に表示されません。だから、例えば、存在する場合(おそらく)IFS=$' \t\n'
変数は、我々が見ることができます:
IFS='
'
…代わりに。
私のegrep
解決策はこれ(そして最終的には他の類似のもの)を適切に表示します。
bash -c $'a() { echo "\nA=B"; }; unset A; set | egrep "^\w+="' | grep ^A
表示であるため反対投票A=B"
->失敗!
私はおそらく以前に答えを盗んだことがあります ...とにかくfuncとは少し異なります:
##
# usage source bin/nps-bash-util-funcs
# doEchoVars
doEchoVars(){
# if the tmp dir does not exist
test -z ${tmp_dir} && \
export tmp_dir="$(cd "$(dirname $0)/../../.."; pwd)""/dat/log/.tmp.$$" && \
mkdir -p "$tmp_dir" && \
( set -o posix ; set )| sort >"$tmp_dir/.vars.before"
( set -o posix ; set ) | sort >"$tmp_dir/.vars.after"
cmd="$(comm -3 $tmp_dir/.vars.before $tmp_dir/.vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
echo -e "$cmd"
}
これを行う簡単な方法は、スクリプトを実行する前にシステム環境変数を設定してbash strictモードを使用し、diffを使用してスクリプトのものだけをソートすることです。
# Add this line at the top of your script :
set > /tmp/old_vars.log
# Add this line at the end of your script :
set > /tmp/new_vars.log
# Alternatively you can remove unwanted variables with grep (e.g., passwords) :
set | grep -v "PASSWORD1=\|PASSWORD2=\|PASSWORD3=" > /tmp/new_vars.log
# Now you can compare to sort variables of your script :
diff /tmp/old_vars.log /tmp/new_vars.log | grep "^>" > /tmp/script_vars.log
/tmp/script_vars.logでスクリプトの変数を取得できるようになりました。または少なくともそれに基づいた何か!
パーティーには少し遅れますが、ここに別の提案があります:
#!/bin/bash
set_before=$( set -o posix; set | sed -e '/^_=*/d' )
# create/set some variables
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c
set_after=$( set -o posix; unset set_before; set | sed -e '/^_=/d' )
diff <(echo "$set_before") <(echo "$set_after") | sed -e 's/^> //' -e '/^[[:digit:]].*/d'
差分+ sedの所望の形式ですべてのスクリプトに定義された変数を出力パイプラインコマンドライン(OPの後に指定されています)。
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c
-o posix
nowを使用した素敵な呼び出しでは、diffには変数のみが含まれます。