🎄 21/25. 在 Raku 中水平地合并文件
— 焉知非鱼欢迎来到Raku One-Liner Advent Calendar的第21天!到本季即将结束的日历只剩下几天了,所以让我们在剩下的日子里收集尽可能多的东西,今天我们将几个文件合并到一个文件中 🙂
我们今天的目标是获取两个(或三个或更多)文件并逐行复制其内容。例如,我们想要合并两个日志文件,知道它们的所有行都相互对应。
文件 a.txt:
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:
"/favicon.ico" failed (No such file)
"/favicon.ico" failed (No such file)
"/robots.txt" failed (No such file)
"/robots.txt" failed (No such file)
我们的第一个单行程序阐述了这个想法:
.say for [Z~] @*ARGS.map: *.IO.lines;
假设程序运行如下:
$ raku merge.pl a.txt b.txt
对于命令行中的每个文件名(@*.ARGS.map
),将创建一个IO::Path
对象(.IO
),并读取文件中的行(.lines
)。
在两个文件的情况下,我们有两个序列,然后使用应用了连接中缀~的zip元运算符Z逐行连接。
在那一步之后,我们得到另一个序列,我们可以逐行打印(.say for
)。
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)
结果形式上是正确的,但是让我们在原始行之间添加一个空格。这是单行程序的更新版本:
.trim.say for [Z~] @*ARGS.map: *.IO.lines.map: *~ ' '
这里,空格字符附加到每一行的末尾(.map: *~ ' '
),并且由于在组合行的末尾将有一个额外的空格,它将被trim
方法删除。可以使用它的兄弟,trim-trailing(或者如果你关心原始尾随空格恰好在第二个文件中的正则表达式)。
通过上述更改,文件现在完美合并:
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)
将同一文件合并到自身或提供两个以上的文件没有问题,例如:
$ raku merge.pl a.txt a.txt a.txt
今天就这样,明天再来!