다음 파일이 있습니다.
AA,true
AA,false
BB,false
CC,false
BB,true
DD,true
중복 항목을 찾고 동일한 열 값을 가진 행을 제거하려고 합니다 true
.
출력은 다음과 같아야 합니다.
AA,false
BB,false
CC,false
DD,true
답변1
간단한 버전:
sort input.txt | awk -F, '!a[$1]++'
"false"는 "true"보다 먼저 알파벳순으로 정렬되며 여기서 Awk 명령은 각각의 고유한 첫 번째 필드 값의 첫 번째 행만 유지합니다.
"true"는 유지하고 "false"는 유지하지 않으려면 역정렬하고 동일한 Awk 명령에 전달한 다음 다시 역정렬하세요.
답변2
awk -F, '$2 == "false" {data[$1]=$2 } $2=="true" { if ( data[$1]!="false" ) { data[$1]=$2 } } END { OFS=","; for (item in data) { print item,data[item] }}' input
설명을 위해 스크립트를 수직으로 확장합니다.
BEGIN {
FS="," # Set the input separator; this is what -F, does.
}
$2 == "false" { # For any line whose second field is "false", we
data[$1]=$2 # will use that value no matter what.
}
$2=="true" { # For lines whose second field is "true",
if ( data[$1]!="false" ) { # only keep if if we haven't yet seen a
data[$1]=$2 # "false"
}
}
END { # Now that we have tabulated our data, we
OFS="," # can print it out by iterating through
for (item in data) { # the array we created.
print item,data[item]
}
}
답변3
perl -F, -lane '
exists $h{$F[0]} or $h[$h{$F[0]}=@h]=$_;
$h=$_; /,false$/ or $_=$h for $h[$h{$F[0]}];
END{ print for @h; }
' duplicates.file
데이터 구조:
- 키는 첫 번째 필드(AAA, BBB, CCC 등)의 해시
%h
이며 해당 값은 키가 발생한 순서를 알려주는 숫자입니다. 예를 들어 AAA 키 => 0, BBB 키 => 1, CCC 키 => 2입니다. @h
해당 요소는 인쇄 순서에 포함된 행의 배열입니다. 따라서 데이터에서 true와 false가 모두 발견되면 false 값이 배열에 저장됩니다. OTW, 데이터 유형이 있으면 존재합니다.
또 다른 방법은 GNU sed를 사용하는 것입니다.
sed -Ee '
G
/^([^,]*),(false|true)\n(.*\n)?\1,\2(\n|$)/ba
/^([^,]*)(,true)\n(.*\n)?\1,false(\n|$)/ba
/^([^,]*)(,false)\n((.*\n)?)\1,true(\n|$)/{
s//\3\1\2\5/;h;ba
}
s/([^\n]*)\n(.*)$/\2\n\1/;s/^\n*//
h;:a;$!d;g
' duplicates.file
FWIW, 위의 GNU-sed 코드에 해당하는 POSIX는 다음과 같습니다.
sed -e '
G
/^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2$/ba
/^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2\n/ba
/^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2$/ba
/^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2\n/ba
/^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false$/ba
/^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false\n/ba
/^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true$/{
s//\3\1\2/
h
ba
}
/^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true\n/{
s//\3\1\2\n/
h
ba
}
y/\n_/_\n/
s/\([^_]*\)_\(.*\)$/\2_\1/;s/^_*//
y/\n_/_\n/
h;:a;$!d;g
' duplicates.file
설명하다
- 이 방법에서는 인쇄할 최종 결과를 보관 공간에 저장합니다.
- 읽은 행마다 홀드 공간을 패턴 공간에 추가하여 홀드 공간을 기준으로 현재 행의 기존 상태를 확인합니다.
- 이제 비교 중에 5가지 일이 발생할 수 있습니다.
- a) 현재 행은 예약된 행의 어딘가와 일치하며 false:false입니다.
- [조치] 동일한 에러 상태가 발견되어 아무런 조치도 취하지 않습니다.
- b) 현재 라인은 유지되는 라인의 어딘가와 일치하며 true:true입니다.
- [조치] 이제 동일한 실제 상태가 발견되었으므로 아무것도 수행하지 마십시오.
- c) 현재 라인은 유지 관리 라인의 어딘가와 일치하며 true:false입니다.
- [조치] 이미 오류 상태가 존재하여 아무런 조치도 취하지 않습니다.
- d) 현재 행은 예약된 행의 어딘가와 일치하며 false:true입니다.
- [조치] 실제 와이어와 정확히 동일한 위치에 가짜 와이어를 교체해야 하기 때문에 약간의 작업이 필요합니다.
- e) 현재 라인이 홀드 라인의 어떤 위치와도 일치하지 않습니다.
- [작동] 현재 행을 끝으로 이동합니다.
- a) 현재 행은 예약된 행의 어딘가와 일치하며 false:false입니다.
결과
AA,false
BB,false
CC,false
DD,true
답변4
2단계 sort
솔루션
sort -k1,1 -k2,2 -t, file | sort -k1,1 -t, -u
첫 번째 sort
패스는 레코드를 필드별로 클러스터링하며 각 레코드 블록 앞의 레코드는 공통 필드 값을 공유합니다. 두 번째 패스는 필드 내의 각 고유 값에 대한 레코드를 생성하도록 설정됩니다. 안정적인 순서를 의미하므로 생성된 하나의 레코드는 필드 내의 각 고유 값에 대해 발견된 첫 번째 레코드입니다. 이는 첫 번째 패스에서 수행된 작업으로 인해 두 번째 필드의 레코드입니다.1
false
true
1
sort
1
-u
-u
1
false
sort