仅当第一列重复时才保留最长的行

仅当第一列重复时才保留最长的行

输入:

user@server:~/bar/foobar$ SAT=$(date -dsaturday +%Y-%m-%d); SUN=$(date -dsunday +%Y-%m-%d)
user@server:~/bar/foobar$ awk 'BEGIN {FS="'^'"} {print $1"\t"$3"\t"$6}' STs.csv STt.csv | egrep -w "${SAT}|${SUN}" | sort -u
'ST30074650'        '2015-10-17 10:00'
'ST30074650'    '[email protected]'  '2015-10-17 10:00'
'ST30085367'    '[email protected]'  '2015-10-18 13:00'
'ST30086369'        '2015-10-17 13:00'
'ST30115016'    '[email protected]'  '2015-10-18 13:00'
'ST30124587'        '2015-10-18 09:00'
'ST30123591'        '2015-10-18 09:00'
user@server:~/bar/foobar$ 

所需输出:

user@server:~/bar/foobar$ SAT=$(date -dsaturday +%Y-%m-%d); SUN=$(date -dsunday +%Y-%m-%d)
user@server:~/bar/foobar$ awk 'BEGIN {FS="'^'"} {print $1"\t"$3"\t"$6}' STs.csv STt.csv | egrep -w "${SAT}|${SUN}" | sort -u | SOMEMAGIC
'ST30074650'    '[email protected]'  '2015-10-17 10:00'
'ST30085367'    '[email protected]'  '2015-10-18 13:00'
'ST30086369'        '2015-10-17 13:00'
'ST30115016'    '[email protected]'  '2015-10-18 13:00'
'ST30124587'        '2015-10-18 09:00'
'ST30123591'        '2015-10-18 09:00'
user@server:~/bar/foobar$ 

问题:因此,如果第一列重复,例如:“ST30074650” - 应该只保留较长的行。怎么有人在“SOMEMAGIC”能做到这一点。

答案1

我不明白 SOMEMAGIC 与它有什么关系

试试这个 awk 文件

{ if ( $1 in a ) {
     if ( length(a[$1]) < length($0)) a[$1]=$0 ;
            } # $1 in a
  else  a[$1]=$0 ; }

END { for ( b in a ) {print a[b] ;}  }

使用它(无需预排序)

... egrep -w "${SAT}|${SUN}" | awk -f u.awk | sort

答案2

使用 perl 一行:

perl -a -e '$line{$F[0]} = $_ if (length($_) > length($line{$F[0]})) ; END { foreach (sort keys %line) { print $line{$_} } };'  STs.csv STt.csv

或者,采用更易于阅读的独立 Perl 脚本形式:

#! /usr/bin/perl -a

$line{$F[0]} = $_ if (length($_) > length($line{$F[0]})) ;

END {
  foreach (sort keys %line) { print $line{$_} }
};

这本质上是与Archemar的答案相同的算法,但是是inperl而不是awk.简单来说:使用输入的第一个字段作为散列数组的键,如果输入的当前行比我们为数组存储的长(默认为 perl 中的空字符串),则存储当前行。一旦我们读取了所有输入(即完成),就打印出哈希的每个元素。

答案3

user@machine:~/tmp$ cat f1
'ST30074650'    '[email protected]'  '2015-10-17 10:00'
'ST30085367'    '[email protected]'  '2015-10-18 13:00'
'ST30086369'        '2015-10-17 13:00'
'ST30115016'    '[email protected]'  '2015-10-18 13:00'
'ST30124587'        '2015-10-18 09:00'
'ST30123591'        '2015-10-18 09:00'
'ST30074650'        '2015-10-17 10:00'

user@machine:~/tmp$ sort -r f1 |uniq -w 12 |sort
'ST30074650'    '[email protected]'  '2015-10-17 10:00'
'ST30085367'    '[email protected]'  '2015-10-18 13:00'
'ST30086369'        '2015-10-17 13:00'
'ST30115016'    '[email protected]'  '2015-10-18 13:00'
'ST30123591'        '2015-10-18 09:00'
'ST30124587'        '2015-10-18 09:00'
  • 首先对整行按相反顺序排序,以首先获得较长的行
  • uniq 仅检查前 12 个字符将保留仅比较 12 个字符的第一(较长)行
  • 可选的最终排序以获得自然顺序

答案4

重构您的代码(由于缺乏原始输入数据而未经测试)

awk -F '^' -v OFS='\t' \
           -v sat=$(date -d saturday +%F) \
           -v sun=$(date -d sunday +%F) \
'
    $6 !~ "^"sat && $6 !~ "^"sun {next}
    { line = $1 OFS $3 OFS $6 }
    length(line) > lines[$1] {lines[$1] = line}
    END { for (key in lines) print lines[key] }
' STs.csv STt.csv | sort

sort使用 GNU awk,您可以通过使用省略尾随

    END { 
        PROCINFO["sorted_in"] = "@ind_str_asc"
        for (key in lines) print lines[key] 
    }

相关内容