有效地将传入的单词行划分到列上?

有效地将传入的单词行划分到列上?

考虑一个由单字组成的流,例如

$ echo foo bar baz quux xyxxy thud | tr ' ' '\n'
foo
bar
baz
quux
xyxxy
thud

我说“一个单词”是为了表示除了换行符之外没有空格。我想通过填写固定数量的字段(不是单个字符)每行,一次一行。对于少量数据,xargs 可以很好地完成此操作:

$ echo foo bar baz quux xyxxy thud | tr ' ' '\n' | xargs -n 2
foo bar
baz quux
xyxxy thud

但是这样使用 xargs 很慢。我有数百 GB 的文本需要处理,因此我非常希望我的写入吞吐量达到 50 MB/s 左右,我知道这个硬件可以做到(上面的 xargs 慢了几个数量级。)

标准工具箱中是否有更好的工具?如果需要,我可以写一些东西,但我更喜欢使用已有的文本过滤器。

答案1

我能想到的最好的办法是

$ echo foo bar baz quux xyxxy thud | tr'''\n'\
  | perl -lne '$x.=" $_"; if(!($. % 2)){打印 $x; $x="";} END{打印 $x if $x}'
 富吧
 巴兹·库克斯
 xyxxy 砰

或者可以说是更优雅的,尽管并不短

$ echo foo bar baz quux xyxxy thud bang| tr ' ' '\n' \
  | perl -ne ‘chomp; 打印“$_ "; 打印“\n” if (!($. % 3)); END {打印“\n”}’
巴兹酒吧
quux xyxxy 砰

效率?

$ time perl -e ‘打印“foo\n”为(1..10000)’| xargs -n 3 > /dev/null

实际 0 分 1.330 秒
用户 0分0.500秒
系统 0 分 0.830 秒


$ time perl -e ‘打印“foo\n” for (1..10000)’ \
  | perl -ne ‘chomp; 打印“$_ "; 打印“\n” if (!($. % 3)); END {打印“\n”}’ \
  > /dev/null

实际 0分0.060秒
用户 0分0.030秒
系统 0分0.030秒

最初我尝试了 1000000 个单词,但是我厌倦了等待 xargs,尽管 perl 是 1.45 秒

(在 AMD-64 x2 5600+ 2.8GHz 处理器、4GB RAM 的 Vista-32 环境下对 andLinux 进行了计时)

答案2

pr被严重低估了。以下是我得出的结论:

% echo foo bar baz quux xyxxy thud | tr ' ' '\n' | pr -2 -a -s' ' -t
富吧
巴兹·库克斯
xyxxy 砰

选项可能因系统而异;请参阅pr手册页。

我没有尝试衡量它的性能。

相关内容