6

我有一个从 argv 读取命令行参数的 C 程序。是否可以制作管道将文件的内容作为命令行参数重定向到我的程序?假设我有一个arguments.dat包含以下内容的文件:

0 0.2 302 0

我希望我的程序被调用:

./myprogram 0 0.2 302 0

我尝试了以下方法:

cat arguments.dat | ./myprogram

没有成功。

4

3 回答 3

14

xargs是你的答案:

cat arguments.dat | xargs ./myprogram

或者更简单:

xargs -a arguments.dat ./myprogram

查看手册以了解自定义的多种方法xargs。例如,您可以逐行而不是逐字阅读,并且可以在更复杂的替换中使用参数。

于 2011-07-05T15:21:57.360 回答
9

对于大多数 shell,您可以使用以下命令将文件的内容插入命令行$(<filename)

./myprogram $(<arguments.dat)

如果您的外壳不支持该功能,那么其​​中一种较旧的方法将起作用:

./myprogram $(cat arguments.dat)
./myprogram `cat arguments.dat`   # need this one with csh/tcsh

(您确实知道命令行参数和文件输入之间的区别,对吧?为什么希望将命令行参数通过管道传递到程序中?)

于 2011-07-05T15:24:56.270 回答
4

如果您不希望参数被无声分裂

...也就是说:以下答案适用于不能./myprogram --first-argument "first value"被默默更改为./myprogram --first-argument; ./myprogram "first value".

如果您的论点是一对一的文字

也就是说,如果您的输入如下所示:

--first-argument
first value
--second-argument
second value

你的意思是这样运行:

./myprogram --first-argument "first value" --second-argument "second value"

...那么您应该使用(使用 bash 4.0 或更高版本):

readarray -t args <arguments.dat
./myprogram "${args[@]}"

...或(对于 bash 3.x 也是如此):

args=( )
while IFS= read -r arg; do
  args+=( "$arg" )
done <arguments.dat
./myprogram "${args[@]}"

如果您的论点带有引号或转义以区分它们

也就是说,如果您的文件包含类似的内容(请注意,换行符和不带引号的空格在此处的行为相同):

--first-argument "first value"
--second-argument "second value"

...你的意思是这样运行:

./myprogram --first-argument "first value" --second-argument "second value"

...那么你应该使用:

args=( )
while IFS= read -r -d '' arg; do
  args+=( "$arg" )
done < <(xargs printf '%s\0' <arguments.dat)

如果你控制你的参数格式

使用 NUL 分隔的值。也就是说,这样创建文件:

printf '%s\0' "argument one" "argument two" >arguments.dat

...并将其解析如下:

args=( )
while IFS= read -r -d '' arg; do
  args+=( "$arg" )
done <arguments.dat
./myprogram "${args[@]}"

这将适用于所有可能的参数值,即使是带有文字换行符、文字引号、文字反斜杠或其他不可打印字符的参数值。(文字NUL 在 UNIX 命令行中是不可能的,因为命令行由以 NUL 结尾的字符串组成;因此,NUL 是唯一可以完全安全地用于明确分隔字符串中的参数的字符)。


如果需要跨调用拆分参数

如果所需的结果(当文件中的参数多于可以传递给程序调用的参数时)是程序的多个不同调用,每个调用都接收参数的子集,则本小节是相关的。这是一系列案例,其中xargs适合这项工作的工具。

如果在 GNU 平台上,您可能希望运行xargs -a arguments.dat而不是重定向标准输入;但是,BSD xargs(如在 MacOS 上)不支持此功能,因此此处未演示。

如果您的论点是一对一的文字

使用 GNU xargs(大多数 Linux 平台):

xargs -d $'\n' ./myprogram <arguments.dat

使用 BSD xargs(MacOS、FreeBSD/OpenBSD/等):

xargs -0 ./myprogram < <(tr '\n' '\0' <arguments.dat)

如果您的论点带有引号或转义以区分它们

xargs ./myprogram <arguments.dat

如果您生成了 NUL 分隔的输入

xargs -0 ./myprogram <arguments.dat
于 2018-06-19T21:24:10.443 回答