在 Perl 脚本中打开行的长度

nic*_*cha 2 perl

我想在 Perl 中使用 switch/case 构造。我有一个包含单词序列的文件,我想根据该行包含的单词数对每一行进行不同的处理。

一个示例文件:

w1 w2 w2
w1 w3
Run Code Online (Sandbox Code Playgroud)

所以脚本看起来像这样,但我如何计算每行中的单词数?

given ($number_of_word_in_line) {
   when ($_ > 2) {
       ...
   }
   when ($_ > 3) {
       ...
   }
   default {
       ...
   }
}
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 5

请小心使用switch语句高度实验性

如前所述,“开关”功能被认为是高度实验性的;如有更改,恕不另行通知。特别是,when有一些棘手的行为,预计将来会变得不那么棘手。不要依赖其当前(错误)的实现。在 Perl 5.18 之前given,如果您的代码必须在旧版本的 Perl 上运行,您仍然应该注意一些棘手的行为。

这些棘手,并且改变。

话虽如此,计算字符串中单词的一种方法是先将其拆分

use warnings;
use strict;
use feature 'switch';

my $file = '...';
open my $fh, '<', $file  or die "Can't open $file: $!";

while (my $line = <$fh>)
{
    chomp $line;
    my @words = split ' ', $line;
    my $num_words = @words;

    given ($num_words) {
        when ($num_words > 2) { 
            # ...
        }
    }
}
close $fh;
Run Code Online (Sandbox Code Playgroud)

什么使用了一个事实,即一个标量 ( $num_words) 在分配一个数组 ( @words) 时接收数组的元素数。请参阅perldata 中的上下文

赋值有点特殊,因为它使用左参数来确定右参数的上下文。分配给标量会评估标量上下文中的右侧,[...]

并且在标量上下文中计算的数组产生其元素的数量。


为了在不创建数组变量的情况下获得计数,我们需要将列表分配给标量,这是不可能直接完成的。但是有一些解决方法,例如

my $num_words = () = $line =~ /\w+/g;
Run Code Online (Sandbox Code Playgroud)

其中“运算符” = () =是上下文的游戏,或

my $num_words = @{ [ $line =~ /\w+/g ] };
Run Code Online (Sandbox Code Playgroud)

其中[]获取对内部列表的引用,然后由 取消引用@{ },可能分配给标量的内容。这种方法也适用split ' ', $line

有关列表、数组和标量的大量信息,请参阅此页面


这可以更紧凑地写为

while (<$fh>) {
    chomp;
    my $num_words = @{ [ split ] };
    # ...
}
Run Code Online (Sandbox Code Playgroud)

默认的whilechomp以及split$_可变的。的split也需要一个图案,默认为' ',所以上述是一样的split ' ', $_。该模式' '特别适用于split并匹配任意数量的任何空格,同时丢弃前导和尾随空格。