同じ行の一致[閉じる]

同じ行の一致[閉じる]

ファイルがありますが、ファイルに同じ項目があるかどうかを知りたいです。

ファイルには次のエントリが含まれています。

dn: cn=ccb2fa1a-6efb-4f29-b18b-72e226d76935,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=936480,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>70
dn: cn=715f55d1-e940-42f9-8ae5-25ff1eff6f55,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=7292,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>4024
rdcPosition: cn=8910,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>5209
rdcPosition: cn=7263,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>6725
rdcPosition: cn=936480,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>11
dn: cn=f61e2769-a9c8-486a-914b-92333055b5e5,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=938936,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>74
rdcPosition: cn=942380,ou=Entities,ou=Active,ou=Vault,o=rdc#5#<position><cn>51
dn: cn=7548d048-1288-4b66-97f4-efe15c68fc50,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=311432,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>43
dn: cn=e51f3d78-b9d8-4bcf-b8c5-321519f19515,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=938936,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>35
dn: cn=cf6ddfb2-4261-4169-9e6e-0d6963262b49,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=938936,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>82

「dn:」の下の「rdcPosition」行に重複したエントリがあるかどうかを知る必要があります。たとえば、次のようになります。

dn: cn=65fb5990-4d2f-492e-83fb-c2cbd72d8988,ou=Named,ou=Identities,ou=Active,o
rdcPosition: cn=7688,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>2323
rdcPosition: cn=7688,ou=Entities,ou=Active,ou=Vault,o=rdc#3#<position><cn>2323

どのUnixコマンドを使用すべきかをご存知ですか?

答え1

私が毎日書くクイックスクリプトの種類は次のとおりです。

#!/usr/bin/perl
#

use strict;
use warnings;

#data structures we're gonna need
my %positions; #how many times have we seen a given position
my %registered_lines; #the concatenated lines for the given position 
my $dn; # the current dn section we're in

while (<>)
{
    if (/^dn:/) #beginning of a new dn section (and end of the previous one)
    {
        my $printed = 0; #we want to print the dn line only once
        foreach my $key (keys %positions) #we look at all positions seen in last section
        {
            if ($positions{$key} gt 1) # has the current position been seen more than once
            {
                print $dn unless $printed;
                $printed = 1;
                #print "position $key is repeated $positions{$key} times\n";
                print $registered_lines{$key}; #print all the lines with the position
            }
        }

        #reset variables for the next section
        $dn = $_;
        %positions = ();
        %registered_lines = ();
    }

    if (/^rdcPosition/) #new line
    {
        /(\d+)$/; #have a look at the digits at the end of the line
        my $pos = $1;
        if (exists $positions{$pos}) #have we already seen this position
        {
            $positions{$pos} += 1; #increment the counter
            $registered_lines{$pos} .= $_; #record the line
        }
        else
        {
            $positions{$pos} = 1;
            $registered_lines{$pos} = $_;
        }
    }
}

次のように実行します。

perl script.pl < input_data_file

答え2

「重複項目がありますか?」に興味がある場合は、cat <file> | sort | wc -l合計結果を比較することをお勧めしますcat <file> | sort | uniq | wc -l。重複した内容がある場合はuniq削除され、数が減ります。違いを確認するには、@Igeorgetが投稿したPerlスクリプトを確認してください。

答え3

awk '/^dn:/ {d=1} {if (d) {print buf | "sort|uniq -d"; d=0; buf=""} else {buf=buf$0"\n"}} END {print buf | "sort|uniq -d"}'|grep -v '^$'

Perlバージョンよりはるかに少ない入力=)。もっと簡単かもしれませんが、「どんなパターンでも最後に」awkルールを実行できないようなので、少しシェルコードの重複が必要です。

関連情報