我有一个数据文件,如下所示:
1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 . . .
1 0 4 4 3 1 2 0 0 0 3 1 1 2 1 1 1 1 1 1 0 1 1 3 . . .
0 0 0 0 0 0 0 3 3 1 1 2 3 2 1 2 2 3 1 2 3 1 2 2 . . .
.
.
.
首先,我想在每 5 个相同的值之间插入空格,通过查看第一行将每 5 个相同的数字放在一个列中,然后我不希望在这些组字符之间插入 anz 空格:第一步:
1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 . . .
1 0 4 4 3 1 2 0 0 0 3 1 1 2 1 1 1 1 1 1 0 1 1 3 . . .
0 0 0 0 0 0 0 3 3 1 1 2 3 2 1 2 2 3 1 2 3 1 2 2 . . .
.
.
.
秒步(输出):
11111 11111 1 22222 222 33333 . . .
10443 12000 3 11211 111 10113 . . .
00000 00331 1 23212 231 23122 . . .
.
.
.
同时,在我的真实数据中,我可能想尝试不同的组大小。所以我需要灵活的脚本..请问有什么建议吗?
答案1
这是一个 awk 脚本。您只需更改数字5
即可进行其他分组。
awk '
NR==1{
previous = $1
for(i = 1;i<=NF+1;i++)
if($i!=previous){
col[++numcol] = i
previous = $i
}
}
{ j = 1; start = 1
for(i = 1;i<NF;i++){
printf "%s",$i
if(i==col[j]-1){printf " "; start = col[j++]}
else if((i-start+1)%5==0)printf " "
}
printf "%s\n",$NF
}'
第一部分仅处理第 1 行,并在数组中收集col
每组相同数字的起始列。第二部分不分隔地打印每个字段,除非在起始列的第 5 列上或在序列的末尾。
答案2
其他变体与awk
awk '
NR==1{
for(i=2;i<=NF;i++){
count++
if($(i-1)!=$i || count>4){
D[i]=1
count=0
}
}
}
{
for(i in D)
$i=" "$i
print
}
' OFS="" data.file >new.file
和sed
sed -re '
s/ +//g;s/^/\n/
' -f <(
sed -r '
s/(. )\1*/s_\\n(&)_\n/g
s/\S /./g
s/\n\s*/\\1 \\n_\n/g
s/\\n[^\n]*\n$/ \\n__/
1q
' data.file
) -e '
s/\S{5}/& /g
' data.file >new.file
答案3
一种可能的方法是使用 perl打开包装函数,具有从文件第一行构造的模板。
删除空格后,它使用具有重复反向引用的正则表达式来查找不超过给定的相同字符的最长连续字符串maxwidth
,并将它们的位置存储在数组中。通过减去数组的相邻元素来提取字段宽度,并将其映射到表单的合适模板字符串中A5A5A1A5A3A5A3
以传递给unpack
函数。
#!/usr/bin/perl -l
use strict;
use warnings;
my $filename = shift or die "Usage: $0 FILENAME MAXWIDTH\n";
my $maxwidth = shift or die "Usage: $0 FILENAME MAXWIDTH\n";
open my $infile, $filename or die "Could not open $filename: $!";
my $n = $maxwidth-1;
my $template;
while( my $line = <$infile> ) {
$line =~ s/\s+//g;
if ($. == 1) {
my @ends = (0);
while ($line =~ /(.)\g1{0,$n}/g) {
push(@ends, pos $line);
}
my @fieldwidths = map $ends[$_] - $ends[$_-1], 1 .. $#ends;
# http://stackoverflow.com/a/29821158/4440445
$template = join "", map { 'A' . $_ } @fieldwidths;
# http://stackoverflow.com/a/2725663/4440445
}
my @fields = unpack($template, $line);
print join " ", @fields;
}
close $infile;