为什么在用Perl将unix命令输出写入文件时需要列表上下文?

为什么在用Perl将unix命令输出写入文件时需要列表上下文?,perl,unix,cut,Perl,Unix,Cut,我试图将unix命令的输出输出输出到一个文件句柄(该句柄指向一个输出文件)。最初我的代码是这样的: open (OUT,'>',$out)|| die "cannot open $out"; my $file =`cut -f $list $in`; print OUT $file; close OUT; 它给了我一条“分段错误”错误消息,这对于perl脚本来说是非常罕见的。。。我四处搜索,在下面的第二行和第三行做了一个小小的更改,将输出更改为数组@file,而不是变量$file,不知为

我试图将unix命令的输出输出输出到一个文件句柄(该句柄指向一个输出文件)。最初我的代码是这样的:

open (OUT,'>',$out)|| die "cannot open $out";
my $file =`cut -f $list $in`;
print OUT $file;
close OUT;
它给了我一条“分段错误”错误消息,这对于perl脚本来说是非常罕见的。。。我四处搜索,在下面的第二行和第三行做了一个小小的更改,将输出更改为数组
@file
,而不是变量
$file
,不知为什么,不管出于什么原因,它都起了作用

open (OUT,'>',$out)|| die "cannot open $out";
my @file =`cut -f $list $in`;
print OUT @file;
close OUT;

有人知道它为什么起作用吗?输出到数组和标量之间的区别是什么

我说不出它为什么起作用,但在标量上下文和列表上下文中调用的区别是:

  • 在列表上下文中,
    qx/
    将返回在
    $/
    (输入记录分隔符)上拆分的输出行列表,但包括这些行的结尾
  • 在标量上下文中,它只返回单个字符串
以下是一个例子:

use strict;
use warnings;
use Data::Dump;

my $foo = `perl -e "print qq{foo\nbar baz};"`;
my @bar = `perl -e "print qq{foo\nbar baz};"`;

dd $foo;
dd @bar;
产生

"foo\nbar baz"
("foo\n", "bar baz")

我不能说它为什么会起作用,但在标量上下文和列表上下文中调用的区别在于:

  • 在列表上下文中,
    qx/
    将返回在
    $/
    (输入记录分隔符)上拆分的输出行列表,但包括这些行的结尾
  • 在标量上下文中,它只返回单个字符串
以下是一个例子:

use strict;
use warnings;
use Data::Dump;

my $foo = `perl -e "print qq{foo\nbar baz};"`;
my @bar = `perl -e "print qq{foo\nbar baz};"`;

dd $foo;
dd @bar;
产生

"foo\nbar baz"
("foo\n", "bar baz")

我对您的初始程序进行了快速测试:

#! /usr/bin/env perl
#
use strict;
use feature qw(say);
use warnings;

my $out = "test.out";
my $list = "2";
my $in = "test.txt";
open OUT,'>',$out || die "cannot open $out";
my $file =`cut -f $list $in`;
print OUT $file;
close OUT;
我的测试文件如下所示:

this    that
who     knows
who     cares
I       know
that
knows
cares
know
我的
test.out
文件如下所示:

this    that
who     knows
who     cares
I       know
that
knows
cares
know
如果测试文件不存在,程序仍然运行,我会在STDERR上通过
cut
打印出一个错误。如果我给它一个错误的字段规范,程序仍然运行,我会在STDERR上通过
cut
打印另一个错误

我尝试了一些方法,但无法让程序因分段错误而彻底失败

所以,问题是什么导致了分割错误。它是
cut
还是Perl?在
中的
my$file=
cut-f$list$之后放置一个print语句
打印出$file行,然后查看它们是否打印任何内容。如果他们这样做,问题在于
cut
,而不是Perl。如果不是,那么您的Perl解释器不知何故出现了问题。那么,问题是为什么它在我的系统上工作而不是在你的系统上工作:

  • 您使用的是什么版本的Perl
  • 操作系统到底是什么?这是在Windows下运行的Linux、Mac OSX、Cygwin,还是旧版本的Solaris/SunOS
  • 这就是全部信息吗
  • 您的
    $out
    文件是否已写入

您编写的程序应该可以在我的系统上运行。我在MacOSX10.9上使用Perl5.14,在Linux RHEL盒上使用Perl5.8.8。我还没有在Cygwin上尝试过这一点。

我对您的初始程序进行了快速测试:

#! /usr/bin/env perl
#
use strict;
use feature qw(say);
use warnings;

my $out = "test.out";
my $list = "2";
my $in = "test.txt";
open OUT,'>',$out || die "cannot open $out";
my $file =`cut -f $list $in`;
print OUT $file;
close OUT;
我的测试文件如下所示:

this    that
who     knows
who     cares
I       know
that
knows
cares
know
我的
test.out
文件如下所示:

this    that
who     knows
who     cares
I       know
that
knows
cares
know
如果测试文件不存在,程序仍然运行,我会在STDERR上通过
cut
打印出一个错误。如果我给它一个错误的字段规范,程序仍然运行,我会在STDERR上通过
cut
打印另一个错误

我尝试了一些方法,但无法让程序因分段错误而彻底失败

所以,问题是什么导致了分割错误。它是
cut
还是Perl?在
中的
my$file=
cut-f$list$之后放置一个print语句
打印出$file行,然后查看它们是否打印任何内容。如果他们这样做,问题在于
cut
,而不是Perl。如果不是,那么您的Perl解释器不知何故出现了问题。那么,问题是为什么它在我的系统上工作而不是在你的系统上工作:

  • 您使用的是什么版本的Perl
  • 操作系统到底是什么?这是在Windows下运行的Linux、Mac OSX、Cygwin,还是旧版本的Solaris/SunOS
  • 这就是全部信息吗
  • 您的
    $out
    文件是否已写入

您编写的程序应该可以在我的系统上运行。我在MacOSX10.9上使用Perl5.14,在Linux RHEL盒上使用Perl5.8.8。我还没有在Cygwin上尝试过此操作。

qx
/
readpipe
/标量上下文中的backticks将尝试将外部命令的输出加载到单个标量变量中。在列表上下文中,输出被加载到多个标量的列表中


如果外部命令的输出非常长,Perl可能会因为试图将其塞进单个字符串而窒息,但是创建几个小字符串并将它们加载到数组中没有问题。

qx
/
readpipe
/scalar上下文中的backticks将尝试将外部命令的输出加载到单个标量变量中。在列表上下文中,输出被加载到多个标量的列表中


如果外部命令的输出非常长,Perl可能会因为试图将其塞进单个字符串而窒息,但创建几个小字符串并将其加载到数组中不会有问题。

您得到的真正错误消息是什么?这不是完整的输出。给定代码片段,为什么不使用:
system“剪切-f$list$in>$out”";
这样Perl就不必在将所有输出都写入文件之前接收命令的全部输出了?名称存储在
$in
中的文件有多大。如果它的大小是千兆字节,而您使用的是32位Perl,那么您可能会遇到麻烦,因为32位程序只有几个GiB(小于4 GiB)可用于变量存储。什么是
$in
?你以前定义过吗,还是有一个常数?你能添加一些
打印
语句吗,这样你就可以看到问题出在哪一行了?程序在
my$file=
cut-f$line$in;`上失败了吗?或者在尝试打印时失败了吗?perl版本?什么是$out?真正的错误是什么