我有一个 bash 脚本,在管道上监听命令。当它看到命令时就会运行它。但是,我希望它支持可以稍后调用的 bash 函数的“侧面加载”。
以下是一些输入/输出示例,可让您了解脚本应该执行的操作:
# left of the arrow is input, right of arrow is output
"echo 'test'" -> "test"
"_a() { echo 'test' }" -> ""
"_a" -> "test"
我让它对于普通命令运行良好,但是在尝试加载函数时遇到了问题。我怀疑这是因为我正在子 shell 中执行用户输入,因此父级将无法使用任何定义的函数来执行将来的命令。我曾尝试使用文件描述符将数据存储在(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 常见问题解答:我试图将命令放入变量中,但复杂的情况总是失败!和为什么应该在 bash 中避免评估以及我应该使用什么在实施任何这样做之前。