按第一行中的字段排序两行,然后按第二行的长度排序

问题描述 投票:0回答:3

我想过滤一个具有以下格式的文件:

Name1|Name2|Name3  
ACGRTIDKEBDIVNRDIVFDOCDDIC  
Name4|Name5|Name6  
AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP  
Name1|Name7|Name3 
AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ

产量

Name1|Name7|Name3  
AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ  
Name1|Name2|Name3  
ACGRTIDKEBDIVNRDIVFDOCDDIC  
Name4|Name5|Name6  
AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

我按照第一个名称对文件进行排序,并将第1行和第2行放在一起;但我也希望只留下最长的第二行(这里是留置权1和2,删除第3和第4行)。

我能够使用awk按名称排序:

awk '{if ((NR%1-2)==0) {line=sprintf("%-30s", $0)} else {print line ":" $0}}' file | sort -t '|' -k1 | tr ':' '\n' > newfile

我不知道如何按第二行的长度排序(仅保留)(使用sort -n)?

谢谢

bash sorting awk
3个回答
1
投票

Perl解决方案:

#!/usr/bin/perl
use strict;
use warnings;

my %by_length;
my ($id, $l1);

while (<>) {
    ( sub { $by_length{$id} = {l1 => $l1, l2 => $_}
                if length > length($by_length{$id}{l2} // "")
      },
      sub { $id = (split /\|/)[0]; $l1 = $_ }
    )[$. % 2]->()
}
print @{ $by_length{$_} }{qw{ l1 l2 }} for sort keys %by_length;

哈希值%by_lengthl2子项中存储每个名称的最长行,以及l1下的相应第一行。


1
投票

复杂的awk + sort解决方案:

awk 'NR % 2 == 0{ sub(/\|/, " ", r); print length, r, $0 }{ r = $0 }' file \
| sort -k2,2 -k1,1nr | awk '{ print $2"|"$3 ORS $NF }'

输出:

Name1|Name7|Name3
AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ
Name1|Name2|Name3
ACGRTIDKEBDIVNRDIVFDOCDDIC
Name4|Name5|Name6
AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

奖金解决方案(额外要求):

awk 'NR % 2 == 0{ sub(/\|/, " ", r); print length, r, $0 }{ r = $0 }' file \
| sort -k2,2 -k1,1nr | awk '!a[$2]++{ print $2"|"$3 ORS $NF }'

输出:

Name1|Name7|Name3
AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ
Name4|Name5|Name6
AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

1
投票

以下是如何在不必将整个文件存储在内存中的情况下轻松自如地执行操作:

1)将每对线折叠为1并添加要排序的键:

$ awk -F'|' 'NR%2{n=$1; h=$0; next} {print n, length(), h, $0}' file
Name1 28 Name1|Name2|Name3   ACGRTIDKEBDIVNRDIVFDOCDDIC
Name4 52 Name4|Name5|Name6   AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP
Name1 37 Name1|Name7|Name3  AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ

2)按照您喜欢的顺序对上述输出进行排序:

$ awk -F'|' 'NR%2{n=$1; h=$0; next} {print n, length(), h, $0}' file |
    sort -k1,1 -k2,2nr
Name1 37 Name1|Name7|Name3  AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ
Name1 28 Name1|Name2|Name3   ACGRTIDKEBDIVNRDIVFDOCDDIC
Name4 52 Name4|Name5|Name6   AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

3)保持每个主键值的第一次出现:

$ awk -F'|' 'NR%2{n=$1; h=$0; next} {print n, length(), h, $0}' file |
    sort -k1,1 -k2,2nr |
    awk '!seen[$1]++'
Name1 37 Name1|Name7|Name3  AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ
Name4 52 Name4|Name5|Name6   AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

4)删除步骤1中添加的额外字段,重新分成2行分区,并打印结果:

$ awk -F'|' 'NR%2{n=$1; h=$0; next} {print n, length(), h, $0}' file |
    sort -k1,1 -k2,2nr |
    awk '!seen[$1]++{print $3 ORS $4}'
Name1|Name7|Name3
AGRQHUOQGRINQJIOPQPJGREQPJIRPEQJIRPEQ
Name4|Name5|Name6
AFFHJORJOVFDANJFOONKFANIFNIPNIPNFIPNKFPDNBKFPNBKFP

如果空白字符不适合您作为组合字段的分隔符,则只需选择一个不同的字符(例如制表符或控制字符或......)。

© www.soinside.com 2019 - 2024. All rights reserved.