【问题标题】:Perl: process string with shell command (pipe)Perl:使用 shell 命令(管道)处理字符串
【发布时间】:2014-11-26 11:43:57
【问题描述】:

假设一个管道包含三个程序:

start | middle | end

如果 startend 现在是一个 perl 脚本的一部分,我如何通过 perl 脚本中的 shell 命令管道数据,以便通过 middle

我尝试了以下方法(抱歉缺少严格模式,它应该是一个简单的概念证明):

#!/usr/bin/perl -n

# Output of "start" stage
$start = "a b c d\n";

# This shell command is "middle"
open (PR, "| sed -E 's/a/-/g' |") or die 'Failed to start sed';

# Pipe data from "start" into "middle"
print PR $start;

# Read data from "middle" into "end"
$end = "";
while (<PR>) {
    $end .= $_;
}

close PR;

# Apply "end" and print output
$end =~ s/b/+/g;

print $end;

预期输出:

- + c d

实际输出:

无,直到我按 ENTER,然后我得到- b c dmiddle 命令正在从 start 接收数据并对其进行处理,但输出将发送到 STDOUT 而不是 end。此外,从middle 读取的尝试似乎是从 STDIN 读取的(因此按 ENTER 的相关性)。

我知道这一切都可以在一行 perl(或 sed)中轻松完成;我的问题是如何在 perl 中进行管道,而不是如何替换字符串中的字符。

【问题讨论】:

  • 问题的另一部分是如何在向start 写入数据后关闭middle 的STDIN,同时仍然能够从middle 的STDOUT 中读取直到它关闭。

标签: perl pipe


【解决方案1】:

您可以为此使用IPC::Open2

这段代码创建了两个文件句柄:$to_sed,您可以通过print 向程序发送输入,以及$from_sed,您可以通过readline(或&lt;$from_sed&gt;)读取程序的输出.

use IPC::Open2;

my $pid = open2(my ($from_sed, $to_sed), "sed -E 's/a/-/g'");

通常最简单的方法是使用 shell,但有一个替代调用允许您绕过 shell,而是运行程序并直接填充其 argv。它在链接的文档中有所描述。

【讨论】:

  • 谢谢!下次我会记住的!
  • 现在是时候了!
【解决方案2】:

您的代码在您按下回车键之前什么都不做的原因是因为您使用的是 perl -n。

-n 使 Perl 假设您的程序周围有以下循环,这使得它遍历文件名参数 有点像 sed -n 或 awk:

          LINE:
            while (<>) {
                ...             # your program goes here
            }

代码中您再次读取文件的部分不返回任何内容。 如果你打开警告,你会发现 perl 不做双向管道。

【讨论】:

  • 哈哈,总是这样。我假设你有一个比你的例子更复杂的问题要解决。做双向 IO 很难。 This might help.
  • 我回到了三个单独的脚本和一个 shell 管道,即使它稍微不那么整洁,它也能正常工作!出于好奇,我主要是在看一个 in-perl 管道解决方案。
猜你喜欢
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-10
相关资源
最近更新 更多