パイプからコマンドを受け取るbashスクリプトがあります。コマンドを見て実行します。しかし、後で呼び出すことができるbash関数の「サイドローディング」をサポートしたいと思います。
以下は、スクリプトが実行する必要があるタスクのアイデアを提供するいくつかの入出力の例です。
# left of the arrow is input, right of arrow is output
"echo 'test'" -> "test"
"_a() { echo 'test' }" -> ""
"_a" -> "test"
通常のコマンドでは正常に機能しますが、機能のロードに問題があります。私はこれがサブシェルでユーザー入力を実行しているので、親は定義された関数を使用して将来のコマンドを実行できないためだと思います。ファイル記述子を使用して(stdout
およびstderr
)にデータを保存しようとしましたが、eval
機能しませんでした。現在、次のようなものがあります。
exec 3>&1
eval 'echo "Hello World"' >&3
read -u 3 var
exec 3>&-
echo "$var"
可能ですか?
答え1
これはあなたに役立ちます:
$ cat runcmd
#!/usr/bin/env bash
tmpout=$(mktemp) || exit
tmperr=$(mktemp) || exit
trap 'rm -f -- "$tmpout" "$tmperr"; exit' EXIT
while IFS= read -r -a cmd; do
printf '==========\n'
declare -p cmd
eval "${cmd[@]}" > "$tmpout" 2>"$tmperr"
readarray -t out < "$tmpout"
readarray -t err < "$tmperr"
declare -p out
declare -p err
done
$ cat <<'EOF' | ./runcmd
echo 'test of echo with globbing * and variables $RANDOM and spaces'
_a() { echo 'test of a()'; }
_a
awk 'BEGIN{print "multi line\noutput string"; print "and multi\nline error\nmessage" | "cat>&2"}'
EOF
==========
declare -a cmd=([0]="echo 'test of echo with globbing * and variables \$RANDOM and spaces'")
declare -a out=([0]="test of echo with globbing * and variables \$RANDOM and spaces")
declare -a err=()
==========
declare -a cmd=([0]="_a() { echo 'test of a()'; }")
declare -a out=()
declare -a err=()
==========
declare -a cmd=([0]="_a")
declare -a out=([0]="test of a()")
declare -a err=()
==========
declare -a cmd=([0]="awk 'BEGIN{print \"multi line\\noutput string\"; print \"and multi\\nline error\\nmessage\" | \"cat>&2\"}'")
declare -a out=([0]="multi line" [1]="output string")
declare -a err=([0]="and multi" [1]="line error" [2]="message")
しかし、入力として提供されたコードを実行するプログラムを書くのは危険ですので、必ず読んでください。Bash FAQ:変数にコマンドを入れようとしていますが、複雑な場合は常に失敗します!そしてBashで評価を避けるべき理由と何を使うべきですか?これを実装する前に。