如何获取未修改的命令行参数以“包装”另一个命令行工具?

5

我希望写一个名为foo的脚本,它可以使用Bash或Perl并调用bar命令,且参数与命令行中传入的参数一致。

在Perl中实现这个功能有一个简单的方法:

#!/bin/perl

my $args=join(' ', @ARGV);
`bar $args`;

然而,ARGV中的值已经被Shell处理过了,因此如果我调用
 foo "I wonder, \"does this work\""

以下是调用 bar 函数的方法:

 bar I wonder "does this work"

我该如何获取原始命令行以便简单地原封不动地传递它?

3个回答

12

在shell处理参数之前,您无法获取perl可执行文件的参数。但是,您可以确保shell不会再次处理它们:

system('bar', @ARGV);

对比。

system("bar @ARGV");

请参阅 perldoc -f system
如果只有一个标量参数,系统将检查是否存在 shell 元字符。如果存在,则将整个参数传递给系统的命令 shell 进行解析(在 Unix 平台上,这是 "/bin/sh -c",但在其他平台上可能不同)。如果参数中没有 shell 元字符,则将其拆分为单词并直接传递给“execvp”,这更有效。
如果您需要读取程序的输出,请使用进程句柄并以相同的方式传递参数(不带插值)。
open my $barhandle, '-|', 'bar', @ARGV or die "Can't call bar: $!";
while (my $line = <$barhandle>)
{
    # do something with $line...
}
close $barhandle;

在Perl中,有很多种方式可以调用程序;请参见Perl的反引号、system和exec之间有什么区别?以获取主要选项的良好概述。


当然需要考虑的一个问题是,<code>system()</code> 的返回值是程序执行的返回值,而不是程序输出。如果你想收集它的输出,可能需要将输出重定向到文件并读取该文件。 - atk
@atk:在这种情况下,您可以使用进程句柄。 - Ether
@ysth:确实,我们甚至之前已经讨论过这个问题:https://dev59.com/BXRA5IYBdhLWcg3w2x6W - Ether

3
非常简单。查看系统调用(LIST)变量的系统调用。
system('bar', @ARGV);

perldoc -f system


3
在bash中:
exec bar "$@"

这将保留参数中的空格。但是,I/O重定向不属于该术语内的参数(但原始调用所执行的I/O重定向将持续到调用的“bar”命令,除非您更改它)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接