🎄 21/25. 在 Perl 6 中水平地合并文件

欢迎来到Perl 6 One-Liner Advent Calendar的21天!到本季即将结束的日历只剩下几天了,所以让我们在剩下的日子里收集尽可能多的东西,今天我们将几个文件合并到一个文件中 🙂

我们今天的目标是获取两个(或三个或更多)文件并逐行复制其内容。例如,我们想要合并两个日志文件,知道它们的所有行都相互对应。

文件 a.txt:

1
2
3
4
2018/12/20 11:16:13 
2018/12/20 11:17:58
2018/12/20 11:19:18
2018/12/20 11:24:30

文件 b.txt:

1
2
3
4
"/favicon.ico" failed (No such file)
"/favicon.ico" failed (No such file)
"/robots.txt" failed (No such file)
"/robots.txt" failed (No such file)

我们的第一个单行程序阐述了这个想法:

1
.say for [Z~] @*ARGS.map: *.IO.lines;

假设程序运行如下:

1
$ perl6 merge.pl a.txt b.txt

对于命令行中的每个文件名(@*.ARGS.map),将创建一个IO::Path对象(.IO),并读取文件中的行(.lines)。

在两个文件的情况下,我们有两个序列,然后使用应用了连接中缀~infix~)的zip元运算符Z逐行连接。

在那一步之后,我们得到另一个序列,我们可以逐行打印(.say for)。

1
2
3
4
2018/12/20 11:16:13"/favicon.ico" failed (No such file)
2018/12/20 11:17:58"/favicon.ico" failed (No such file)
2018/12/20 11:19:18"/robots.txt" failed (No such file)
2018/12/20 11:24:30"/robots.txt" failed (No such file)

结果形式上是正确的,但是让我们在原始行之间添加一个空格。这是单行程序的更新版本:

1
.trim.say for [Z~] @*ARGS.map: *.IO.lines.map: *~ ' '

这里,空格字符附加到每一行的末尾(.map: *~ ' '),并且由于在组合行的末尾将有一个额外的空格,它将被trim方法删除。可以使用它的兄弟,trim-trailing(或者如果你关心原始尾随空格恰好在第二个文件中的正则表达式)。

通过上述更改,文件现在完美合并:

1
2
3
4
2018/12/20 11:16:13 "/favicon.ico" failed (No such file)
2018/12/20 11:17:58 "/favicon.ico" failed (No such file)
2018/12/20 11:19:18 "/robots.txt" failed (No such file)
2018/12/20 11:24:30 "/robots.txt" failed (No such file)

将同一文件合并到自身或提供两个以上的文件没有问题,例如:

1
$ perl6 merge.pl a.txt a.txt a.txt

今天就这样,明天再来!