내 파일은 다음과 같습니다.
pw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
-
두 번째 열을 기준으로 이 파일을 구분 기호로 병합하여 결과가 다음과 같도록 하고 싶습니다 .
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254341,gcmj7krrx5x6nf8r
답변1
awk
당신의 친구입니다
$ cat 299360
ipw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
$ awk -v FS="," '/^$/{next} # for empty line go to next record
{if(NR==1){ # checking for first record
f2[$2]=$1;next} # Adding $1 to array f2 at index $2
else{
if($2 in f2){ # Check if $2 is already an index in f2
f2[$2]=f2[$2]"-"$1;next #appending "-$1" to current value
}
else{
f2[$2]=$1;next
}
}}
END{ # This line will be processed at the end
for(i in f2){ # for all the indexes i in f2
printf "%s,%s\n",i,f2[i] #printing in the desired format
}
}
' 299360
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg
설명하다
FS=","
– FS는 awk의 내장 변수로 필드 구분자를 나타냅니다. 필드 구분 기호를 다음으로 설정하면 구분 기호로,
설정됩니다 .,
$1
$2
등을 통해 필드에 액세스 할 수 있습니다 .- awk 스크립트는 작은따옴표로 묶입니다.
'awk-script-goes-here'
NR
레코드 번호(현재 처리 중인 레코드 번호)를 나타내는 awk 내장 변수입니다. 기본적으로 각 행은 레코드입니다.- field2로 색인된 연관 배열 (예: )을
f2[$2]=$1
설정하고 있습니다 .f2
$2
$2 in f2
인덱스가 배열에 이미 존재하는지 확인하십시오.- 그리고 자명
if-else
하다 .printf
- awk의 블록은
END
마지막에만 실행됩니다. 즉, 모든 레코드가 처리된 후에 실행됩니다. for(i in f2)
awk에서 연관 배열을 구문 분석하는 데 사용되는 for 루프 구조입니다. 이것은 또 다른 표현으로,for every index i in f2 do something
- 위의
for
루프는 배열을 순서대로 인쇄하지 않을 수 있습니다. 그러나sort
bash 명령을 사용하여 배열을 정렬할 수 있습니다. next
후속 명령을 처리하지 않고 다음 레코드로 이동합니다./pattern/
awk의 패턴 확인; 패턴은^$
빈 줄을 확인합니다.
인용하다
awk 전문가가 되고 싶다면,효과적인 awk 프로그래밍꼭 읽어야 할 책입니다.
추악한 한 줄짜리
awk -v FS="," '/^$/{next}{if(NR==1){f2[$2]=$1;next}else{if($2 in f2){f2[$2]=f2[$2]"-"$1;next}else{f2[$2]=$1;next}}}END{for(i in f2){printf "%s,%s\n",i,f2[i]}}' 299360
노트:이상적으로는 awk 스크립트에서 줄바꿈을 하드코딩하는 것은 좋지 않습니다 printf "%s,%s\n",i,f2[i]
. printf "%s,%s\n",i,f2[i];print
추가 이식성을 위해 .
답변2
GNU와 함께데이터 혼합:
datamash -t, -s -g 2 collapse 1 <data.txt | sed 's/,/-/2g'
결과:
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg
답변3
존재하다 perl
:
#! /usr/bin/perl
use strict;
my %mergecol = ();
while(<>) {
s/#.*//; # strip comments
next if (m/^\s*$/); # skip empty lines
chomp;
my ($val,$key) = split ',';
push @{ $mergecol{$key} }, $val;
};
foreach my $k (keys %mergecol) {
printf "%s,%s\n", $k, join('-', @{ $mergecol{$k} } );
}
이 while
루프는 입력을 읽고 HoA(해시 배열) 구조, 즉 각 요소가 배열("목록"이라고도 함)인 연관 배열을 생성합니다. 해시의 키는 두 번째 필드이고, 각 목록의 요소는 동일한 두 번째 필드가 있는 행의 첫 번째 필드입니다.
스크립트 끝에서 각 레코드에 대해 키 이름, 쉼표, 를 포함하는 HoA 한 줄을 인쇄합니다 -
.
다음으로 실행:
$ ./rock.pl rock.txt
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
또는 "한 줄"로 줄여서 셸 명령이나 스크립트에 포함합니다.
$ perl -n -e '
s/#.*//;
next if (m/^\s*$/);
chomp; ($v,$k)=split ","; push @{ $mc{$k} }, $v;
END {
foreach $k (keys %mc) { printf "%s,%s\n", $k, join("-",@{$mc{$k}}) }
}' rock.txt
또는
$ perl -e 'while(<>) {s/#.*//;next if (m/^\s*$/);chomp;($v,$k)=split ",";push @{$mc{$k}}, $v};
foreach $k (keys %mc) {printf "%s,%s\n",$k,join("-",@{$mc{$k}})}' rock.txt
해시 또는 연관 배열은 다음과 같습니다.본질적으로 무질서한, 출력을 정렬하려면 입력을 파이프하거나 sort
위 줄을 사용하십시오.(sort keys %f)
foreach my $k
답변4
GNU의 2차원 배열awk
awk -F, '{
a[$2][$1]
}
END{
for (i in a) {
c=0; printf "%s,", i;
for (j in a[i]) {
++c; printf "%s%s", j, length(a[i]) == c? "\n": "-"
}
}
}' file