我想在 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)
如前所述,“开关”功能被认为是高度实验性的;如有更改,恕不另行通知。特别是,
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)
默认的while
,chomp
以及split
是$_
可变的。的split
也需要一个图案,默认为' '
,所以上述是一样的split ' ', $_
。该模式' '
特别适用于split
并匹配任意数量的任何空格,同时丢弃前导和尾随空格。