我基本上想这样做:
$_ = "some content that need to be escaped &>|\"$\'`\s\\";
qx{echo $_ | foo}
Run Code Online (Sandbox Code Playgroud)
这里有两个问题。首先$_需要转义的内容,因为它可以包含二进制数据。其次,调用的echo效率可能稍低。
如何简单地将一些内容作为 STDIN 传送到 Perl 中的命令?
以下假设@cmd包含程序及其参数(如果有)。
my @cmd = ('foo');
Run Code Online (Sandbox Code Playgroud)
如果要捕获输出,可以使用以下任一方法:
use String::ShellQuote qw( shell_quote );
my $cmd1 = shell_quote('printf', '%s', $_);
my $cmd2 = shell_quote(@cmd);
my $output = qx{$cmd1 | $cmd2};
Run Code Online (Sandbox Code Playgroud)
use IPC::Run3 qw( run3 );
run3(\@cmd, \$_, \my $output);
Run Code Online (Sandbox Code Playgroud)
use IPC::Run qw( run );
run(\@cmd, \$_, \my $output);
Run Code Online (Sandbox Code Playgroud)
如果您不想捕获输出,可以使用以下任何一种:
use String::ShellQuote qw( shell_quote );
my $cmd1 = shell_quote('printf', '%s', $_);
my $cmd2 = shell_quote(@cmd);
system("$cmd1 | $cmd2");
Run Code Online (Sandbox Code Playgroud)
system('/bin/sh', '-c', 'printf "%s" "$0" | "$@"', $_, @cmd);
Run Code Online (Sandbox Code Playgroud)
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote(@cmd);
open(my $pipe, '|-', $cmd);
print($pipe $_);
close($pipe);
Run Code Online (Sandbox Code Playgroud)
open(my $pipe, '|-', '/bin/sh', '-c', '"$@"', 'dummy', @cmd);
print($pipe $_);
close($pipe);
Run Code Online (Sandbox Code Playgroud)
use IPC::Run3 qw( run3 );
run3(\@cmd, \$_);
Run Code Online (Sandbox Code Playgroud)
use IPC::Run qw( run );
run(\@cmd, \$_);
Run Code Online (Sandbox Code Playgroud)
如果您不想捕获输出,但也不想看到它,则可以使用以下任一方法:
use String::ShellQuote qw( shell_quote );
my $cmd1 = shell_quote('printf', '%s', $_);
my $cmd2 = shell_quote(@cmd);
system("$cmd1 | $cmd2 >/dev/null");
Run Code Online (Sandbox Code Playgroud)
system('/bin/sh', '-c', 'printf "%s" "$0" | "$@" >/dev/null', $_, @cmd);
Run Code Online (Sandbox Code Playgroud)
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote(@cmd);
open(my $pipe, '|-', "$cmd >/dev/null");
print($pipe $_);
close($pipe);
Run Code Online (Sandbox Code Playgroud)
open(my $pipe, '|-', '/bin/sh', '-c', '"$@" >/dev/null', 'dummy', @cmd);
print($pipe $_);
close($pipe);
Run Code Online (Sandbox Code Playgroud)
use IPC::Run3 qw( run3 );
run3(\@cmd, \$_, \undef);
Run Code Online (Sandbox Code Playgroud)
use IPC::Run qw( run );
run(\@cmd, \$_, \undef);
Run Code Online (Sandbox Code Playgroud)
笔记:
使用的解决方案printf将对传递到程序的 STDIN 的数据大小施加限制。
使用的解决方案printf无法将 NUL 传递给程序的 STDIN。
所提出的使用 IPC::Run3 和 IPC::Run 的解决方案不涉及外壳。这避免了问题。
您可能应该使用system和capture来自 IPC::System::Simple 而不是内置system并qx获得“免费”错误检查。
这个答案是一种非常幼稚的做法。很容易陷入僵局。不要使用它!
如果父级向附加到子级 STDIN 的管道写入了足够的数据,并且子级在从其 STDIN 读取之前向附加到其 STDOUT 的管道输出了足够多的数据,则会出现死锁。(在某些系统上这可能只有 4KB。)解决方案涉及使用 select、线程等。更好的解决方案是使用已经为您解决问题的工具(IPC::Run3 或 IPC::跑步)。IPC::Open2 和 IPC::Open3 级别太低,在大多数情况下没有用处
我将保留原始答案,但鼓励读者从其他答案中选择解决方案。
您可以使用IPC::Open2open2来读取和写入同一进程。
现在你不需要关心逃避任何事情。
use IPC::Open2;
use FileHandle;
my $writer = FileHandle->new;
my $reader = FileHandle->new;
my $pid = open2( $reader, $writer, 'wc -c' );
# write to the pipe
print $writer 'some content that need to be escaped &>|\"$\'`\s\\';
# tell it you're done
$writer->close;
# read the out of the pipe
my $line = <$reader>;
print $line;
Run Code Online (Sandbox Code Playgroud)
这将打印48.
请注意,您不能""对显示的确切输入使用双引号,因为反斜杠的数量\是错误的。
有关详细信息,请参阅perldocopen和perlipc 。
| 归档时间: |
|
| 查看次数: |
993 次 |
| 最近记录: |