【问题标题】:Perl - Using backquotes missing outputPerl - 使用反引号缺少输出
【发布时间】:2012-04-06 20:10:10
【问题描述】:

大家好,我需要捕获外部命令的输出,因此我使用反引号。 但是,当命令到达换行符时,将省略输出。其中 $_ = AD

@lines = `"C:/Program Files/Veritas/NetBackup/bin/admincmd/bppllist" $_ -U"`
测试:test1 测试:test2 测试:test3 测试:test4

实际输出: @行

测试:test1 测试:test2

感谢您的宝贵时间。

    print HTML "<h2 id='pol'>Policy Configuration\n</h2>" ;

  @bpllist =`"$admincmd/bppllist.exe"` or die print "$admincmd/bppllist.exe not found or could not be executed";
foreach (@bpllist) 
{
  print HTML "<div><table class='table'>\n";
  @lines = `"$admincmd/bppllist" $_ -U` or die print       "$admincmd/bpplinfo $_ -U not found or could not be executed";
   print HTML "\t<tr>\n\t<td><b>Policy name: <b></td><td>$_</td>\n\t</tr>\n" ;

  foreach (@lines) {

chop;
 ($var, $value) = split(/:/,$_,2);
 $var = "" if !defined($var);
 $value = "" if !defined($value);
print HTML "\t<tr>\n\t<td>$var</td><td>$value</td>\n\t</tr>\n" ;

  } 
  print HTML "</table></div>";
  }

@bpllist 的输出:

  AD
  Sharepoint
  Echchange
  Vmware

【问题讨论】:

  • 不,不作为评论,edit您上面的问题。
  • $_ 包含什么?你为什么没有发布你正在尝试的完整示例?
  • use strict; use warnings;
  • 不要将join 与 LIST 上下文结合使用。使用join$output 或仅使用@output

标签: perl stdout capture


【解决方案1】:

以下是使用反引号捕获衍生进程的 STDOUT 和 STDERR 的方法:

my $output = join('', `command arg1 arg2 arg3 2>&1`);

它的工作原理不依赖于command 输出中的换行符。

如果你还需要向command的STDIN发送文本,那么使用IPC::Open3。


稍微清理了您的代码。它对我有用。

use strict;
use warnings;
use 5.10.0;

# something missing here to set up HTML file handle
# something missing here to set up $admincmd

print HTML q{<h2 id='pol'>Policy Configuration\n</h2>};
my @bpllist = `"$admincmd/bppllist.exe"` 
  or die "$admincmd/bppllist.exe not found or could not be executed\n";
for my $policy (@bpllist) {
  print HTML q{<div><table class='table'>\n};
  my @lines = `$admincmd/bpplinfo.exe $policy -U 2>&1`;
  print HTML qq{\t<tr>\n\t<td><b>Policy name: <b></td><td>$policy</td>\n\t</tr>\n} ;
  for my $pair (@lines) {
    chomp($pair); # only remove newlines, not other characters
    my ($var, $value) = split /:/, $pair, 2;
    $var //= '';
    $value //= '';
    print HTML qq{\t<tr>\n\t<td>$var</td><td>$value</td>\n\t</tr>\n} ;
  }
  print HTML q{</table></div>};
}

更新 2

您似乎在 Windows 上执行此操作?

我不认为2&gt;&amp;1 技巧在那里会起作用。

【讨论】:

  • 当我尝试这样做时,我得到:'C:/Program' 未被识别为内部或外部命令,
  • 该命令没有反引号 - 这些是双引号 - StackOverflow 评论吃掉了它们吗?也可以使用 $lines (对于单个字符串中的所有行),或者不使用 join()。
  • 请更新您的问题以包含不适合您的真实代码。确保use strict; use warnings;
  • 更新上面的问题。在每行代码之前放置空格,并在完整代码的上下各留一个空行。
【解决方案2】:

不要使用qx 或反引号,然后使用shell 命令来重定向输出,而是试试核心模块IPC::Cmd。特别是,它的可导出函数&amp;run 将方便地为您捕获 STDOUT 和 STDERR。摘自:

### in list context ###
my( $success, $error_message, $full_buf, $stdout_buf, $stderr_buf ) =
run( command => $cmd, verbose => 0 );

【讨论】:

  • 看起来@David-SkyMesh 其他人在评论中指出了原因。无论如何,&amp;IPC::Cmd::run 不会给你带来这样的麻烦。
【解决方案3】:

也许该命令将其输出发送到标准错误。

试试这个:

my $output = `'command' -ARG -L 2>&1`;

问候,

【讨论】:

  • 那是因为$output = `blah` 在 SCALAR 上下文中只捕获第一行。您需要在 LIST 上下文中执行 @output = `blah` 。我的答案中的 join() 强制 LIST 上下文。
  • 好的,但是换行符之后的输出仍然丢失!
  • 再次编辑您的问题,不要遗漏任何内容!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多