아래와 같은 파일이 있습니다.
47196436 47723284 name1 1.77273
42672249 52856963 name2 1.06061
52856963 430695 name2 1.16667
55094959 380983 name3 1.55613
17926380 55584836 name4 1.02461
3213456 34211 name4 1.11
54321 34211 name4 1.23
처음 두 열은 내 테이블의 기본 키에 해당합니다. 동일한 이름이 있으면 모든 키가 동일한 행에 있도록 행을 병합하려고 합니다.
출력을 얻으려고합니다.
47196436 47723284 name1
42672249 52856963 430695 name2
55094959 380983 name3
17926380 55584836 3213456 34211 54321 name4
다음 명령을 사용하여 부분적으로 달성할 수 있었습니다.
awk '{ x[$3]=x[$3] " " $2; }
END {
for (k in x) print k,x[k] >"OUTPUT1";
}' ccc.txt
그러나 그것은 나에게 올바른 출력을 제공하지 않습니다. 위 명령을 추가로 수정하려면 도움이 필요합니다.
답변1
서투르지만 일을 완수한 것 같다
awk '$3 != prev {if (NR != 1) print prev; prev=$3; delete a};
!($1 in a){a[$1]++; printf "%s ", $1};
!($2 in a){a[$2]++; printf "%s ", $2};
END {print prev}' ccc.txt
47196436 47723284 name1
42672249 52856963 430695 name2
55094959 380983 name3
17926380 55584836 3213456 34211 54321 name4
답변2
일방 perl
통행:
$ perl -ane '$h{$F[2]} .= " ".$F[0]." ".$F[1];
END {
for $k (sort keys %h) {
print $_," " for grep {!$seen{$_}++} split(" ",$h{$k});
print "$k\n";
}
}' file
47196436 47723284 name1
42672249 52856963 430695 name2
55094959 380983 name3
17926380 55584836 3213456 34211 54321 name4
답변3
Perl의 또 다른 접근 방식은 다음과 같습니다.
$ perl -ane 'foreach(@F[0..1]){$k{$F[2]}{$_}++}
END{
foreach $v (sort keys(%k)){
print "$_ " foreach(keys(%{$k{$v}}));
print "$v\n"
};
} ' file
그러면 다음이 생성됩니다.
47723284 47196436 name1
42672249 430695 52856963 name2
380983 55094959 name3
34211 55584836 17926380 54321 3213456 name4
설명하다
좋습니다. 위의 Perl 스크립트는 Perl의 이해하기 쉬운 예가 아니라는 점을 인정합니다. 나는 많은 트릭을 사용했고 그들은 코드를 난독화했습니다. 여기서는 동일한 솔루션을 제안하지만 스크립트 형식으로 더 장황한 접근 방식을 사용합니다.
#!/usr/bin/perl
## This is the hash that will store our values.
my %k;
## Read through the input file line by line
## saving each line as $line. This is what the -n
## switch to perl means, only there each line is saved
## in the special variable $_.
while (my $line=<>) {
## Split the line into the @F array. This is
## what the -a switch does.
#chomp($line);
my @F=split(/\s+/,$line);
## Populate the %k hash that we defined at the beginning.
## This is a hash of hashes, it looks like this:
## $hash{key1}{key2}=value
## In this case, we are saying:
## $hash{3rd field}{1st field}=1
## $hash{3rd field}{2nd field}=1
## This just serves to add the 1st and 2nd fields
## to the list of fields for this $F[2] (the 3rd field, the name).
## A side effect of this is that hash keys are unique so duplicates
## are automatically removed.
$k{$F[2]}{$F[0]}=1;
$k{$F[2]}{$F[1]}=1;
}
## We have now finished processing the file
## (this is the END{} block above), so let's print.
## This saves the keys of the hash %k in the @names array
## sorted alphabetically.
my @names=(sort keys(%k));
## Go through each of the names, saving
## them as $name
foreach my $name (@names) {
## Now, iterate through the values associated
## with the current $name. These are saved as the
## keys of the hash %k{$name}
foreach my $value ( (keys(%{$k{$name}})) ){
print "$value ";
}
## Now print the name as well
print "$name\n";
}
위의 스크립트는 제가 게시한 스크립트와 정확히 동일한 작업을 수행하며, 더 깔끔한 구문을 사용하도록 확장되었습니다.
답변4
를 사용해도 괜찮다면 gawk >= 4.0
다음을 사용하세요(특별한)는 선택적 이름과 키 순서를 사용하여 원하는 출력을 생성합니다.
NF {
Names[$3][$1] = 1;
Names[$3][$2] = 1;
}
END {
PROCINFO["sorted_in"] = "@ind_str_asc"; # if you want `Name` ordered
for (Name in Names) {
PROCINFO["sorted_in"] = "@ind_num_asc"; # if you want `Key` ordered
for (Key in Names[Name]) {
printf("%s ", Key);
}
print Name;
}
}
다음을 제공합니다:
47196436 47723284 name1
430695 42672249 52856963 name2
380983 55094959 name3
34211 54321 3213456 17926380 55584836 name4