如何在 (ba)sh 命令中 get/parse 重定向的 "target"
How to get/parse the "target" of a redirect in (ba)sh command
我必须通过模拟器 运行 二进制文件,但二进制文件是庞大而复杂的基准测试套件的一部分。那么在正常系统上会是这样的:
# First form
./binary -long=list -of=args <input.txt >std.out 2>std.err
需要看起来像这样:
# second form
simulator -c ./binary -o "-long=list -of=args" -i input.txt --output=std.out --errout=std.err
基准测试套件正在传递命令,即在 (bash) 变量中带有所有内容(args 和重定向)的二进制文件,例如$CMD="./binary -long=list -of=args <input.txt >std.out 2>std.err"
,我需要找出所有重定向的目标(即示例中的 intpu.txt
、std.out
和 std.err
),以便我可以转换命令在第一种形式到第二种形式的命令)。
那么有没有办法,例如,告诉 bash 执行命令 $CMD
,其中包含二进制文件、args 和重定向,并解析它,然后 return,比方说,什么是输入重定向(即 input.txt
),或其他重定向之一(std.out
或 std.err
)?
当然不用手动解析...
像这样:
$ CMD="./binary -long=list -of=args <input.txt >std.out 2>std.err"
$ bash -secret_option_to_parse_redirect_target=input "$CMD"
intpu.txt
$ bash -secret_option_to_parse_redirect_target=output "$CMD"
std.out
$ bash -secret_option_to_parse_redirect_target=error "$CMD"
std.err
如果您相信 cmd
可以解析为一个简单的命令,您可以使用 eval
添加一个包装器来读取命令行和主动重定向。在 https://replit.com/@CharlesDuffy2/GrouchyHelplessInformationtechnology#main.sh
处查看此代码 运行
请注意,这需要操作系统的 /proc/*/fd
接口与 Linux 提供的接口兼容。
read_fd() {
local fd_num dest_var fd_dest default_val bash_pid=$BASHPID
fd_num=; dest_var=; default_val=${3:-"/proc/self/fd/$fd_num"}
printf -v "$dest_var" %s "$default_val"
[[ -e /proc/$bash_pid/fd/$fd_nume ]] || return
fd_dest="$(readlink "/proc/$bash_pid/fd/$fd_num")" || return
[[ -e $fd_dest ]] || return
printf -v "$dest_var" %s "$fd_dest"
}
parse_cmd() {
read_fd 0 stdin_src
read_fd 1 stdout_dest
read_fd 2 stderr_dest
argv_dest=( "$@" )
}
...用作:
# all-caps variable names are reserved; do not use them in your own code
cmd="./binary -long=list -of=args <input.txt >std.out 2>std.err"
# inputs need to exist for redirections to work
touch input.txt
eval "parse_cmd $cmd"
echo "stdout destination is $stdout_dest"
echo "stderr destination is $stderr_dest"
echo "stdin source is $stdin_src"
echo "argument list follows, one per line:"
printf ' - %q\n' "${argv_dest[@]}"
echo
echo "to run this, you could use:"
echo "${argv_dest[*]@Q} <$stdin_src >$stdout_dest 2>$stderr_dest"
我必须通过模拟器 运行 二进制文件,但二进制文件是庞大而复杂的基准测试套件的一部分。那么在正常系统上会是这样的:
# First form
./binary -long=list -of=args <input.txt >std.out 2>std.err
需要看起来像这样:
# second form
simulator -c ./binary -o "-long=list -of=args" -i input.txt --output=std.out --errout=std.err
基准测试套件正在传递命令,即在 (bash) 变量中带有所有内容(args 和重定向)的二进制文件,例如$CMD="./binary -long=list -of=args <input.txt >std.out 2>std.err"
,我需要找出所有重定向的目标(即示例中的 intpu.txt
、std.out
和 std.err
),以便我可以转换命令在第一种形式到第二种形式的命令)。
那么有没有办法,例如,告诉 bash 执行命令 $CMD
,其中包含二进制文件、args 和重定向,并解析它,然后 return,比方说,什么是输入重定向(即 input.txt
),或其他重定向之一(std.out
或 std.err
)?
当然不用手动解析...
像这样:
$ CMD="./binary -long=list -of=args <input.txt >std.out 2>std.err"
$ bash -secret_option_to_parse_redirect_target=input "$CMD"
intpu.txt
$ bash -secret_option_to_parse_redirect_target=output "$CMD"
std.out
$ bash -secret_option_to_parse_redirect_target=error "$CMD"
std.err
如果您相信 cmd
可以解析为一个简单的命令,您可以使用 eval
添加一个包装器来读取命令行和主动重定向。在 https://replit.com/@CharlesDuffy2/GrouchyHelplessInformationtechnology#main.sh
请注意,这需要操作系统的 /proc/*/fd
接口与 Linux 提供的接口兼容。
read_fd() {
local fd_num dest_var fd_dest default_val bash_pid=$BASHPID
fd_num=; dest_var=; default_val=${3:-"/proc/self/fd/$fd_num"}
printf -v "$dest_var" %s "$default_val"
[[ -e /proc/$bash_pid/fd/$fd_nume ]] || return
fd_dest="$(readlink "/proc/$bash_pid/fd/$fd_num")" || return
[[ -e $fd_dest ]] || return
printf -v "$dest_var" %s "$fd_dest"
}
parse_cmd() {
read_fd 0 stdin_src
read_fd 1 stdout_dest
read_fd 2 stderr_dest
argv_dest=( "$@" )
}
...用作:
# all-caps variable names are reserved; do not use them in your own code
cmd="./binary -long=list -of=args <input.txt >std.out 2>std.err"
# inputs need to exist for redirections to work
touch input.txt
eval "parse_cmd $cmd"
echo "stdout destination is $stdout_dest"
echo "stderr destination is $stderr_dest"
echo "stdin source is $stdin_src"
echo "argument list follows, one per line:"
printf ' - %q\n' "${argv_dest[@]}"
echo
echo "to run this, you could use:"
echo "${argv_dest[*]@Q} <$stdin_src >$stdout_dest 2>$stderr_dest"