具有带空格的命令行参数的 Perl 脚本

Posted

技术标签:

【中文标题】具有带空格的命令行参数的 Perl 脚本【英文标题】:Perl script that has command line arguments with spaces 【发布时间】:2009-08-12 18:19:29 【问题描述】:

我觉得我在这里遗漏了一些非常明显的东西,但我似乎无法弄清楚发生了什么。我有一个从 C 代码调用的 perl 脚本。脚本 + 参数是这样的:

my_script "/some/file/path" "arg" "arg with spaces" "arg" "/some/other/file"

当我在 Windows 中运行它时,Perl 正确地将它识别为 5 个参数,而当我在 SunOS Unix 机器上运行它时,它识别出 8 个,将带有空格的 arg 分割成单独的 args。

不确定它是否有任何区别,但在 Windows 中我的运行方式如下:

perl my_script <args>

在 Unix 中,我只是将其作为可执行文件运行,如上所示。

知道为什么 Unix 没有正确管理该参数吗?

编辑:

下面是调用perl脚本的代码:

 char cmd[1000];
 char *script = "my_script";
 char *argument = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";
 sprintf( cmd, "%s %s >1 /dev/null 2>&1", script, arguments);
 system( cmd );

不完全是这样,因为我更动态地构建参数字符串,但这就是要点。

另外,这是我读取参数的代码:

($arg1, $arg2, $arg3, $arg4, $arg5) = @ARGV;

我知道这太天真了,但是这个脚本只能从 C 应用程序中运行,所以不需要更复杂的

【问题讨论】:

请提供在 Unix 中用于从 C 代码调用 perl 脚本的确切代码。 请提供更多关于如何加载参数字符串的细节。我相信您的问题出在该代码中。 我很确定它不是...我在其中放置了一些调试代码,它会在调用系统之前输出该 cmd,这正是我最初发布的内容。 【参考方案1】:

大概

system("my_script \"/some/file/path\" \"arg\" \"arg with spaces\" \"arg\" \"/some/other/file\");

导致一切都通过 bash (因为需要解释 shebang 行,吃掉你传递的引号)。同样,据推测,可以通过直接调用 perl 而不是依靠 shell 来找到它来避免该问题(尽管如果路径上的 perl 与 shebang 行上提供的不同,这可能是一个问题) .

更新:

鉴于您的:

char *argument = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";

你可能想试试:

char *argument = "\\\"arg1\\\" \\\"arg2\\\" \\\"arg3 with spaces\\\" \\\"arg4\\\" \\\"arg5\\\"";

另一个更新:

感谢您接受我的回答,但是,我的整个理论可能是错误的。

我在GNU bash, version 4.0.28(2)-release (i686-pc-linux-gnu) 中尝试了上述argument 的双重反击版本,结果通过了

[思南@kas src]$ ./t '"arg1"' '"arg2"' ''arg3' '和' '空格'' '"arg4"' '"arg5"'

而原来的 argument 就像一个魅力。我对此感到有些困惑。也许 SUN 上的 shell 不是 bash 或者可能有其他事情发生。

【讨论】:

嗯,这似乎是问题所在。当我更新 Unix cmd 以实际调用 perl 时,它完全符合我的预期。我仍然不确定为什么它不起作用,尤其是考虑到 Juliano 的复制尝试。那好吧。至少它有效。【参考方案2】:

您是否忘记了 SunOS 上的引号?

如果你这样做

perl script arg1 arg2 "arg3 with spaces" arg4 arg5

你应该很好。否则,请尝试切换 shell。

【讨论】:

【参考方案3】:

现在问题已更新,我仍然无法重现您的结果:

~% cat test.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
        char cmd[1000];
        char *script = "./my_script";
        char *arguments = "\"arg1\" \"arg2\" \"arg3 with spaces\" \"arg4\" \"arg5\"";
        sprintf( cmd, "%s %s", script, arguments);
        system( cmd );
        return 0;


~% cat my_script
#!/usr/bin/perl
($arg1, $arg2, $arg3, $arg4, $arg5) = @ARGV;
print "arg1 = $arg1\n";
print "arg2 = $arg2\n";
print "arg3 = $arg3\n";
print "arg4 = $arg4\n";
print "arg5 = $arg5\n";

~% gcc test.c

~% ./a.out
arg1 = arg1
arg2 = arg2
arg3 = arg3 with spaces
arg4 = arg4
arg5 = arg5

~%

您的配置还有其他问题。


上一个答案:

Unix shell 解释带引号的参数 作为一个单一的论点。你可以做一个 快速测试:

for i in a b "c d e" f; do echo $i; done

结果如你所愿 be: "c d e" 被视为一个单一的 论据。

我认为你有问题 脚本,在参数处理中 逻辑。

【讨论】:

【参考方案4】:

SunOS 内核对 shebang 解释器的处理是否可能非常糟糕?尝试将其作为“/path/to/perl script args”而不是“script args”运行,看看是否有任何变化。

【讨论】:

以上是关于具有带空格的命令行参数的 Perl 脚本的主要内容,如果未能解决你的问题,请参考以下文章

Perl和python命令行参数的区别

Perl 不接收命令行参数?

如何将强制和可选命令行参数传递给 perl 脚本?

用awk如何读取shell命令行上的参数(参数可以是带空格的)

将 0 作为命令行参数传递的问题

如何编写一个带命令行参数的Python文件