1

我想要一个相对紧凑的命令来执行文本文件的逐行去交错,即

a1
a2
a3
a4
b1
b2
b3
b4
c1
c2
c3
c4
d1
d2
d3
d4

映射到

a1
b1
c1
d1
a2
b2
c2
d2
a3
b3
c3
d3
a4
b4
c4
d4

交织深度应该是可调的。这些行本身不包含任何有用的结构来帮助该过程,上面的示例只是一个用于演示目的的玩具示例。我可以使用什么工具来做到这一点?

4

6 回答 6

2

基本上,您正在做的是将数据读入二维数组。当您读入它时,您可以(例如)将数据逐行放入数组中。

然后当你写出数据时,你逐列遍历数组。调整您所做的(去)交错只需要不同大小的数组(或者至少您使用不同数量的数组,尽管如果您选择,您可以将数组大小本身固定)。

于 2013-04-18T15:07:33.493 回答
2

sort可以做到!

$ sort -k1.2 your_file

-k1.2从第二个字符开始按第一个字段排序。

输出:

a1
b1
c1
d1
a2
b2
c2
d2
a3
b3
c3
d3
a4
b4
c4
d4
于 2013-04-18T15:01:27.280 回答
1

更新

终于明白了你的问题,感谢TLP,我建议这个解决方案。它需要命令行上的深度和输入文件名:

$ perl deinter.pl 4 interleaved.txt

并将重新排序的数据打印到 STDOUT。

use strict;
use warnings;

my $depth = shift;
my @data = <>;

for my $start (0 .. $depth-1) {
  for (my $i = $start; $i < @data; $i += $depth) {
    print $data[$i];
  }
}

输出

a1
b1
c1
d1
a2
b2
c2
d2
a3
b3
c3
d3
a4
b4
c4
d4

以前的解决方案

这是一种将整个文件读入内存的技术,构建一组用于比较的键,并对数据的索引进行排序,以便它们可以以新的顺序打印。

通过修改提取键字段的正则表达式并更改排序块以使排序顺序正确,可以根据您的目的对其进行更改。

如果您的文件很大,那么可能只需要在内存中构建键数组,并将文件中的其余数据保留为在输出时读取。

use strict;
use warnings;

open my $fh, '<', 'interleaved.txt' or die $!;
my @data = <$fh>;

my @keys = map [ /^(.)(.)/ ], @data;

my @sorted = sort {
  $keys[$a][1] <=> $keys[$b][1] or
  $keys[$a][0] cmp $keys[$b][0]
} 0 .. $#keys;

print $data[$_] for @sorted;
于 2013-04-18T15:24:43.723 回答
1

根据您的新要求,根据元素在文件中的位置重新排序元素:

use strict;
use warnings;

my @sorted;
my $depth = 4;     # the adjustable interleaving depth

while (<DATA>) {  
    my $num = ($. % $depth) - 1;  # $. is input line number
    push @{ $sorted[$num] }, $_;
}
for (@sorted) {
    print @$_;
}


__DATA__
a1
a2
a3
a4
b1
b2
b3
b4
c1
c2
c3
c4
d1
d2
d3
d4

<DATA>请注意,可以通过更改为<>并运行以下命令在输入文件上测试脚本:

perl script.pl input.txt
于 2013-04-18T15:46:16.307 回答
1

这可能对您有用(GNU sed 和排序):

sed '1{x;s/^/1/;x};G;s/\n/\t/p;x;y/1234/2341/;x;d' file|sort -sk2|sed 's/\t.*//'
于 2013-04-18T21:18:16.050 回答
0

我想感谢他们的投入和回答,这激发了解决方案BorodinTLP好丑,不过我喜欢

awk 'BEGIN{v=4}{now=(NR-1)%v; STOR[now] = STOR[now] "\n" $0;} END {for (v in STOR) print STOR[v]}'

它还具有打印虚假换行符的缺陷(嗯,附加到数组开头的换行符),但我可以处理。

编辑:

换行符的解决方案:

awk 'BEGIN{v=4}{now=(NR-1)%v; STOR[now] = STOR[now] "\n" $0;} END {for (v in STOR) print substr(STOR[v],2)}'
于 2013-04-18T16:14:28.160 回答