![bash - 独自の名前空間を汚染しないソースコード[他のスクリプトから変数を取得する安全な方法]](https://linux33.com/image/84570/bash%20-%20%E7%8B%AC%E8%87%AA%E3%81%AE%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93%E3%82%92%E6%B1%9A%E6%9F%93%E3%81%97%E3%81%AA%E3%81%84%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%5B%E4%BB%96%E3%81%AE%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E3%81%8B%E3%82%89%E5%A4%89%E6%95%B0%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B%E5%AE%89%E5%85%A8%E3%81%AA%E6%96%B9%E6%B3%95%5D.png)
他のbashスクリプトの変数の内容を呼び出しスクリプトの変数に割り当てたいと思います。
特に次のファイルがありますsource
。https://projects.archlinux.org/svntogit/packages.git/plain/trunk/PKGBUILD?h=packages/firefox(およびその他の類似文書)。
ファイルにはなどの変数が含まれていますdepends
。makedepends
だから私のスクリプトにはいくつかのステートメントがあります。
depends="$(source "/path/to/file" ; printf '%s' "${depends[@]}")"
makedepends="$(source "/path/to/file" ; printf '%s' "${makedepends[@]}")"
...
したがって、デフォルトでは、各ステートメントはファイルをインポートして内容を印刷する独自のサブシェルを起動します。単一の変数親シェルの変数に。
単一のサブシェルの起動に関連する他の方法はありますか?、ファイルをインポートし、呼び出しシェルで指定されたファイルに割り当てられた指定された変数の内容を取得します。シェルが呼び出される環境を汚染しませんか?
------------------------------------- ----------
Mark Mannが外国のスクリプトを使用する危険性を指摘したので、source
私は結局別の解決策を提案しました。source
これを使用して他のスクリプトの変数(varName =(...)、varName2 = "..."、varname3 = '...'、varName4 = ...)と結果を取得する代わりに:grep
perl
eval
$ grepvars='(license)|(depends)|(makedepends)|(url)|(pkgdesc)|(pkgver)'
$
$ eval $(grep -Pzo "^(${grepvars})=\([^\)\(\`]*\)|^(${grepvars})=\"[^\"\(\`]*\"|^(${grepvars})='\''[^'\'']*'\''|^(${grepvars})=[^\s;\(\`]*" /tmp/above_mentioned_file)
$ echo $url
https://www.mozilla.org/firefox/
$
$ echo ${depends[@]}
gtk3 gtk2 mozilla-common libxt startup-notification mime-types dbus-glib alsa-lib ffmpeg2.8 desktop-file-utils hicolor-icon-theme libvpx icu libevent nss hunspell sqlite ttf-font
答え1
使用eval
。
ソースコードがある場合(/tmp/other.shに):
a=1
b=2
c=3
一部だけが必要な場合は、それを使用してeval
アイテムをインポートできます(/tmp/main.shから)。
eval $(source /tmp/other.sh;
echo a="$a";
echo b="$b";)
echo a is $a "(expect 1)"
echo b is $b "(expect 2)"
echo c is $c "(expect nothing)"
そして実行してください:
$ bash /tmp/main.sh
a is 1 (expect 1)
b is 2 (expect 2)
c is (expect nothing)
警告する:信頼できないスクリプトを実行eval
または実行するsource
ことは非常に危険です。あなたはシェルスクリプトを実行しており、スクリプトはあなたが自分でできることをすべて行うことができます。警告する
答え2
または、同様のものを使用している場合は、次のものをeval
使用しない場合でも、プロセスの置き換えによってこれを行うことができます。bash
source <(source "/path/to/file" ; printf %s\\n "depends=${depends[*]}" "makedepends=${makedepends[*]}")
これは、最初の例と同様に、サブシェルを起動してファイルを取得しますが、値を直接印刷し、コマンド置換を使用する代わりに、割り当てられた形式の値を印刷し、プロセス置換を使用して出力を取得します。
これはあなたの質問の次の部分への完全な答えです。
呼び出しシェルの環境を汚染することなく単一のサブシェルを起動し、ファイルをインポートし、呼び出しシェルで指定されたファイルに割り当てられた指定された変数の内容を取得することに関連する他の方法はありますか?
しかしもちろん外国のスクリプトを調達するには危険があります。信頼できないスクリプトを取得しないでください。
台本を自分で書いたら絶対に確信副作用がなく、出力も生成されない場合は、上記の内容を使用できます。自分のPC。これはしてはいけないことではありません。一度本番スクリプトで。非常に大きなセキュリティ欠陥です。
答え3
source <(cat "/path/to/file" | grep "depends\|makedepends")
ソースはまったくありません/path/to/file
(ワイルドカードアプローチと比較)。不安定性に関する上記の議論を参照してください。また.env
、ファイルまたは同様のファイルの場合は、引用符でdocker-compose
囲まれていない変数を実行せずに変数をプロットする方法で他のスクリプトで使用でき、実行エラーが発生する可能性があります。たとえば、traefik
このようなフロントエンドルールWEB_FRONTEND_RULE=Host:my.host.name;PathPrefix:/my-path-prefix
は動作しますdocker-compose .env
が、ソースでは動作しませんbash
。WEB_FRONTEND_RULE='Host:my.host.name;PathPrefix:/my-path-prefix'
fromでは有効ですが有効ではありbash
ませんdocker-compose
.env
。
答え4
拡張回答ワイルドカードからファイルをインポートした後(すべて同じ警告は、次の場合にのみ表示されます。信じるファイル)、スキャンしてエクスポートした変数名を識別し、その宣言をインポートしてから再エクスポートできます。
source-export() {
local _RC=0
local FILENAME=$1
shift
source <(
source "${FILENAME}" "$@"
_RC=$?
if (( _RC )); then
typeset -p _RC
exit
fi
# show the exported names
PATTERN="\b(?<=export)(\s+\w+)+"
while read -r NAME; do
[[ -n ${NAME} ]] && typeset -p "${NAME}"
done < <(grep -oP "${PATTERN}" "${FILENAME}" | tr ' ' '\n')
)
return ${_RC}
}
注:エクスポートのためにスキャンするために使用するモードはかなり強力でなければなりません(同様の状況処理export A B
)。潜在的により強力な別のアプローチは、派生変数を取得する前後に変数テーブルを区別することです。
例:
$ cat foo.sh
export XXX="432"
YYY=111
export ZZZ="'adfa $*"
export A B
A=1
B=2
C=3
$ source-export foo.sh 3 2 1
$ echo -e "XXX=$XXX\nYYY=$YYY\nZZZ=$ZZZ\nA=$A\nB=$B\nC=$C"
XXX=432
YYY=
ZZZ='adfa 3 2 1
A=1
B=2
C=
比較的:
$ source foo.sh 3 2 1
$ echo -e "XXX=$XXX\nYYY=$YYY\nZZZ=$ZZZ\nA=$A\nB=$B\nC=$C"
XXX=432
YYY=111
ZZZ='adfa 3 2 1
A=1
B=2
C=3
とでbash
テストされましたzsh
。