系统("echo -e $str")无法在perl中正确输出
system("echo -e $str") can not been output rightly in perl
我写了一个像这样的简单 perl 脚本
#!/usr/bin/perl
my $str = "hello\nworld";
my $cmd = "echo -e $str";
system($cmd);
输出为:
-e hello
sh: 2: world: not found
这不是预期的。我想要的是:
hello
world
注意 "echo -e" 可以正确工作,因为当我 运行 跟随命令时,
echo -e "hello\nworld"
输出正确。
有什么解决办法吗?
my $cmd = qq(echo -e "$str");
系统参数字符串中的新行类似于 ;
。它分隔命令。为了不发生这种情况,您需要将其放在引号内。
如果你设置后打印出来$cmd
,你会看到:
echo -e hello
world
... 如果您将其粘贴到 shell 中,您将收到类似的错误消息,尽管没有 -e
。
第一个问题是,当它到达shell 时,字符串缺少引号和非文字换行符。试试这个:
my $str = "hello\nworld";
my $cmd = "echo -e '$str'";
在这种特殊情况下,您可以只使用引号 - echo
的参数中会有一个文字换行符,但只要它被引用就是合法的。
但是,您仍然会在输出中得到文字 -e
,并且不会将 \n
解释为换行符。那是因为 perl 是 运行ning /bin/echo
,而不是 bash 中内置的 echo
。如果你想使用 bash 的内置函数,你必须明确地告诉 perl 到 运行 bash
。但这意味着将 echo 命令本身传递到 bash 的参数中,这引入了 另一个 级别的引用来处理。
这里(实际上到处都是)最好的选择是使用 system
的多参数版本;绕过第一个 shell 级别并直接执行命令。我们仍然需要处理换行符:
my $str = "hello\nworld"; # literal newline
(my $escaped_str = $str) =~ s,\n,\n,g; # escaped newline
为了从 shell 中获得所需的行为,我们需要在 shell 命令中将字符串嵌入单引号中,因为单引号中的任何内容都完全由 shell。在这种情况下,我们只是从 Perl 代码中的文字分配字符串,所以我们确切地知道它包含什么,并且它不包含撇号。但是如果它可能包含撇号,我们应该 运行 它通过另一个转义传递来引用它们,所以嵌入单引号是安全的:
$escaped_str =~ s,','\'',g; # quote any embedded apostrophes
您可能还希望用转义符替换其他字符 - 可能是制表符或回车符 return。这也是进行这些更改的地方。
使用转义字符串构建 bash 命令:
my $command = "echo -ne '$escaped_str'"; # bash command to echo string
像这样手动操作search/replaces很容易出错;有很多边缘情况需要考虑。所以你可能还想看看 CPAN 模块 String::ShellQuote
,其中你可以跳过上面的手动转义并从原始字符串生成转义字符串,如下所示:
my $command = shell_quote("echo", "-ne", $str);
获得转义命令字符串后,使用多参数 system
到 运行 bash 直接将该字符串作为参数:
system('bash', '-c', $command);
总的来说,更重要的是,我会考虑用 Perl 本身的代码替换 shell 命令所做的任何事情;结果将更易于管理,并且可能更便携且性能更高。
我写了一个像这样的简单 perl 脚本
#!/usr/bin/perl
my $str = "hello\nworld";
my $cmd = "echo -e $str";
system($cmd);
输出为:
-e hello
sh: 2: world: not found
这不是预期的。我想要的是:
hello
world
注意 "echo -e" 可以正确工作,因为当我 运行 跟随命令时,
echo -e "hello\nworld"
输出正确。
有什么解决办法吗?
my $cmd = qq(echo -e "$str");
系统参数字符串中的新行类似于 ;
。它分隔命令。为了不发生这种情况,您需要将其放在引号内。
如果你设置后打印出来$cmd
,你会看到:
echo -e hello
world
... 如果您将其粘贴到 shell 中,您将收到类似的错误消息,尽管没有 -e
。
第一个问题是,当它到达shell 时,字符串缺少引号和非文字换行符。试试这个:
my $str = "hello\nworld";
my $cmd = "echo -e '$str'";
在这种特殊情况下,您可以只使用引号 - echo
的参数中会有一个文字换行符,但只要它被引用就是合法的。
但是,您仍然会在输出中得到文字 -e
,并且不会将 \n
解释为换行符。那是因为 perl 是 运行ning /bin/echo
,而不是 bash 中内置的 echo
。如果你想使用 bash 的内置函数,你必须明确地告诉 perl 到 运行 bash
。但这意味着将 echo 命令本身传递到 bash 的参数中,这引入了 另一个 级别的引用来处理。
这里(实际上到处都是)最好的选择是使用 system
的多参数版本;绕过第一个 shell 级别并直接执行命令。我们仍然需要处理换行符:
my $str = "hello\nworld"; # literal newline
(my $escaped_str = $str) =~ s,\n,\n,g; # escaped newline
为了从 shell 中获得所需的行为,我们需要在 shell 命令中将字符串嵌入单引号中,因为单引号中的任何内容都完全由 shell。在这种情况下,我们只是从 Perl 代码中的文字分配字符串,所以我们确切地知道它包含什么,并且它不包含撇号。但是如果它可能包含撇号,我们应该 运行 它通过另一个转义传递来引用它们,所以嵌入单引号是安全的:
$escaped_str =~ s,','\'',g; # quote any embedded apostrophes
您可能还希望用转义符替换其他字符 - 可能是制表符或回车符 return。这也是进行这些更改的地方。
使用转义字符串构建 bash 命令:
my $command = "echo -ne '$escaped_str'"; # bash command to echo string
像这样手动操作search/replaces很容易出错;有很多边缘情况需要考虑。所以你可能还想看看 CPAN 模块 String::ShellQuote
,其中你可以跳过上面的手动转义并从原始字符串生成转义字符串,如下所示:
my $command = shell_quote("echo", "-ne", $str);
获得转义命令字符串后,使用多参数 system
到 运行 bash 直接将该字符串作为参数:
system('bash', '-c', $command);
总的来说,更重要的是,我会考虑用 Perl 本身的代码替换 shell 命令所做的任何事情;结果将更易于管理,并且可能更便携且性能更高。