【发布时间】:2020-01-25 16:01:01
【问题描述】:
我的 Bash 脚本 将一组(多个)参数发送到 C 程序。
这是我的C程序:
$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char **argv )
{
printf("Parameter 1 is: %s \n", argv[1]);
printf("Parameter 2 is: %s \n", argv[2]);
return 0;
}
编译后(如MyCProgram),它的行为正常:
MyCProgram -f "/path/to/file/with spaces"
Parameter 1 is: -f
Parameter 2 is: /path/to/file/with spaces
但是,当尝试向它发送 通过 shell 变量的参数时:
$ var='-f "/path/to/file/with spaces" '
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: "/path/to/file/with
$ MyCProgram "$var"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram '$var'
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram "$(echo $var)"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo "$var")"
Parameter 1 is: -f "/path/to/file/with spaces"
Parameter 2 is: (null)
$ MyCProgram "$(echo '$var')"
Parameter 1 is: $var
Parameter 2 is: (null)
$ MyCProgram '$(echo "$var")'
Parameter 1 is: $(echo "$var")
Parameter 2 is: (null)
$ var="-f '/path/to/file/with spaces' "
$ MyCProgram $var
Parameter 1 is: -f
Parameter 2 is: '/path/to/file/with
我怎样才能获得正确的行为,这与在没有 shell 变量的情况下运行时相同?
注意事项:
- 接受对 Bash 脚本或 C 程序的两种更改。
-
类似的线程似乎发出了类似的问题,但我想说的不一样:
Passing quoted arguments to C program in a shell script
Bash: pass variable as a single parameter / shell quote parameter
根据 Craig Estey 的回答,这很好用:
$ var=(-f "/file with spaces")
$ MyCProgram "${var[@]}"
此方法有效,但前提是我手动(明确)将值分配给var。假设 var 已经分配(即:通过输入读取或文件读取),我会说这里的问题是将其转移到 bash 数组变量。所以:
$ var='-f "/file with spaces"'
$ var2=( $var )
$ MyCProgram "${var2[@]}"
Parameter 1 is: -f
Parameter 2 is: "/file
问题依然存在。
【问题讨论】:
-
Assuming var is already assigned (i.e: via input read or file read)- 那么您应该修复“输入读取”或“文件读取”的方式,以便正确处理带空格的输入。这看起来像 XY 问题 - 您正在尝试在其他地方解决需要解决的问题。您在问如何解析带有"封闭元素的字符串?编写您自己的解析器,它将以您想要的方式正确读取和转义它们。文件名中的不可打印字符应该怎么办?或者如果文件名包含"怎么办? -
您是否查看过特殊变量 $@ 以及您的脚本如何与用户交互?当我想将命令行参数从 shell 的命令行传递给脚本中的子命令时,我使用“$@”,以便在给子命令时引用给脚本的所有参数。
-
引号是shell语法,但变量(和文件)中存储的是data,一般不被视为shell语法(例外:空格作为分隔符和通配符扩展——如果你不引用变量)。您要求的是更多类似于 shell 语法的数据解析。除非您非常清楚要应用哪些解析规则,否则这是相当危险的,而且往往很复杂且容易出错。这就引出了一个重要的问题:你在这里的实际目标是什么?为什么要尝试将 shell 语法与数据混合?有没有更好的办法?
标签: c bash shell parameters