来自反引号的多字参数(命令替换)

时间:2015-11-19 21:47:39

标签: bash shell

假设我有一个包含内容的文件params.txt

--option "option 1" --option "option 2"

我希望能够使用params.txt的内容作为某些程序的命令行参数myProg

./myProg $(cat params.txt)

./myProg `cat params.txt`

但这似乎不起作用:它将多字参数视为多个参数,而不是单引号参数。有没有办法使用命令替换(或其他一些我不知道的bash功能)从params.txt中获取参数并获取

./myProg --option "option 1" --option "option 2"

作为执行的命令?

1 个答案:

答案 0 :(得分:3)

如果params.txt由您信任的人撰写,则可以使用eval执行此操作:

eval "./myProg $(<params.txt)"

安全地写一个eval - 来自脚本的安全流看起来如下:

printf '%q ' --option "option 1" --option "option 2" >params.txt

明确存储参数并在没有the serious security risks caused by eval的情况下使用它们的更好方法是作为NUL分隔的流:

# write params file
printf '%s\0' --option "option 1" --option "option 2" >params

......然后,消费那......

# read params file into array
params=( )
while IFS= read -r -d '' param; do
  params+=( "$param" )
done <params

# use that array to call your program
./myProg "${params[@]}"

请注意,后一种形式与命令替换不兼容,但如果您正在读取比cat更有趣的命令的输出,则可以与进程替换一起使用(最好用简单的重定向代替)。因此:

# this does not work: depends on NULs being stored in a shell variable
while IFS= read -r -d '' param; do params+=( "$param" ); done <<<"$(...command here...)"

# this works
while IFS= read -r -d '' param; do params+=( "$param" ); done < <(...command here...)

请注意,进程替换是POSIX sh中不存在的功能;确保你的shebang用这种支持指​​定一个shell(例如#!/bin/bash)。