如何从文件传递命令行参数
Posted
技术标签:
【中文标题】如何从文件传递命令行参数【英文标题】:How to pass command line parameters from a file 【发布时间】:2011-09-28 22:17:14 【问题描述】:我有一个从 argv 读取命令行参数的 C 程序。是否可以制作管道将文件的内容作为命令行参数重定向到我的程序?假设我有一个文件arguments.dat
,内容如下:
0 0.2 302 0
我希望我的程序被调用:
./myprogram 0 0.2 302 0
我尝试了以下方法:
cat arguments.dat | ./myprogram
没有成功。
【问题讨论】:
【参考方案1】:xargs
是你的答案:
cat arguments.dat | xargs ./myprogram
或者更简单:
xargs -a arguments.dat ./myprogram
查看手册了解自定义xargs
的多种方法。例如,您可以逐行而不是逐字阅读,并且可以在更复杂的替换中使用参数。
【讨论】:
这里有一些注意事项——如果你的文件包含的参数多于单个命令行(请记住,环境变量和命令行参数使用相同的空格)——所以@987654325 @ing 太多或太大的命令行变量会减少最大命令行长度),xargs
将多次运行 ./myprogram
,在调用之间拆分参数。
@CharlesDuffy:好点子。这可能是一个错误,也可能是一个非常需要的功能,具体取决于用例。无论如何,我添加了另一种机制。
@CharlesDuffy:是的,确实如此。 Bash 还有一种方法可以让您使用编辑器编辑命令行。 xargs
有许多先进的操作方式,可以让你引用参数并逐行阅读等等。
@CharlesDuffy:是的,这绝对是我在可重用脚本中所做的。但是,如果它是一次性使用,您大致知道参数是什么,那么简单的 xargs 通常就是您所需要的。
当然。我试图就正确性提出一个论点,因为 *** 的答案本质上是可重复使用的——它(理想情况下)会被很多人阅读和使用(在很多不同的场景中,其中一些用例可能与 OP 不同),因此花在正确处理细节上的时间和精力是非常值得的。也就是说,如果我应该添加一个竞争性答案,请随时告诉我。 :)【参考方案2】:
对于大多数 shell,您可以使用 $(<filename)
将文件的内容插入命令行:
./myprogram $(<arguments.dat)
如果您的 shell 不支持,那么其中一种较旧的方法将起作用:
./myprogram $(cat arguments.dat)
./myprogram `cat arguments.dat` # need this one with csh/tcsh
(您确实知道命令行参数和文件输入之间的区别,对吧?您为什么希望将命令行参数通过管道传递到程序中?)
【讨论】:
“旧方式”不会拆分参数。文件中的所有数据都将作为单个参数加载。 @osgx:这根本不是真的。要使其成为单个参数,您需要将其放在双引号内。 如果您的文件包含"first argument" "second argument"
,这会将"first
作为一个参数,argument"
作为第二个参数,"second
作为第三个参数。如果它包含*.txt
,它将用文本文件列表替换它,而不是保持原样。如果文件包含"*.txt"
,引号将作为字符串的文字部分传递(if 用户没有nullglob
或failglob
导致先验被视为失败的 glob...好吧,如果没有任何名称以文字双引号字符开头和结尾的文件,则失败)。【参考方案3】:
如果您不希望参数被静默分割
...也就是说:以下答案适用于不能将./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[@]"
这适用于所有可能的参数值,即使是带有文字换行符、文字引号、文字反斜杠或其他不可打印字符的参数值。 (在 UNIX 命令行中,文字 NUL 不可能,因为命令行由以 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
【讨论】:
以上是关于如何从文件传递命令行参数的主要内容,如果未能解决你的问题,请参考以下文章
如何将参数从 bat 文件或命令行传递给 plpgsql 函数?
从带有命令行参数的批处理文件运行控制台应用程序,如何在运行时传递参数值? [复制]