我发现这个非常有用的单行,它可以工作,但我无法理解它是如何设法循环遍历文件的两行。
perl6 -ne 'state %l; .say if ++%l{$_} == 1' input-file.txt
答案 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
读取输入。
答案 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