最初の列が繰り返される場合、最長行のみを保持

最初の列が繰り返される場合、最長行のみを保持

入力する:

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 1行使用:

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の答えと同じアルゴリズムですが、代わりに簡単にperl言え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

sortGNU awkを使用すると、次のように末尾を省略できます。

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

関連情報