Perl 6单行打印文件的唯一行

时间:2017-12-21 20:30:51

标签: perl6

我发现这个非常有用的单行,它可以工作,但我无法理解它是如何设法循环遍历文件的两行。

perl6 -ne 'state %l; .say if ++%l{$_} == 1' input-file.txt

3 个答案:

答案 0 :(得分:4)

也许是一个更具可读性的 Raku one-liner 来摆脱重复的行:

raku -e 'lines.unique.join("\n").put;' input-file.txt

简而言之,-n-p 命令行标志均未设置:使用 lines 读取输入。 unique 命令用于使行唯一。由于 lines 会自动截断尾随换行符,因此输出会与 join 一起进行 join("\n") 回溯,以返回逐行输出。

或者:

raku -e '.unique.join("\n").put given lines;' input-file.txt

上面使用了 given 主题化器。根据文档:given 可以跟随一个语句以在它跟随的语句中设置主题。” 同样,-n-p 命令行都不是设置标志:使用 lines 读取输入。

https://docs.raku.org/syntax/given

答案 1 :(得分:3)

只有一个周期 它将所有行收集为%l中的键,其值是它看到的次数。
如果这是第一次(… == 1),它会遇到当前行的副本,而是打印出来。

它基本上与:

相同
my %l;

for $*ARGFILES.lines() {  # this is basically what `-n` does

  ++%l{ $_ };             # update the count

  .say if %l{ $_ } == 1;  # print it if this is the first time it was seen

}

我认为使用… if ++$… == 1代替… unless $…++的原因是&prefix:«++»的性能略高于&postfix:«++»

另一种可能更有效(取决于.unique的实现)编写方式的方法是:

perl6 -e '.put for $*ARGFILES.lines.unique' input-file.txt

答案 2 :(得分:2)

让我们解开这个问题。 -n选项会在代码周围添加for lines() { ... }循环,因此我们有

for lines() { 
    state %l;
    .say if ++%l{$_} == 1
}

为什么state var?没有简单的方法可以在该行的隐式循环的外部作用域中声明变量。否则你会把它写成

my %l;
for lines() { 
    .say if ++%l{$_} == 1
}

%l会跟踪一条线(存储在$_)中的次数。它使用自动化,因此第一次看到一行时,++运算符会自动将其添加到哈希值。

.say$_.say

的简写