다음 파일이 있습니다.
AA,true
AA,false
BB,false
CC,false
BB,true
DD,true
중복을 찾고 열 값이 인 줄을 제거하려고합니다 true
.
출력으로 다음과 같아야합니다.
AA,false
BB,false
CC,false
DD,true
답변
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]
}
}
답변
간단한 버전 :
sort input.txt | awk -F, '!a[$1]++'
“false”는 “true”보다 알파벳순으로 정렬되며 여기서 Awk 명령은 각각의 고유 한 첫 번째 필드 값에 대해서만 첫 번째 행만 유지합니다.
“false”대신 “true”를 유지하려면 역 정렬하여 동일한 Awk 명령에 전달한 후 나중에 다시 정렬하십시오.
답변
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
데이터 구조 :
%h
키가 첫 번째 필드 (AAA, BBB, CCC 등) 인 해시 와 해당 값은 키가 발생한 순서를 나타내는 숫자입니다. 따라서, 예를 들어, 키 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
위의 GNU 코드에 대한 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
답변
각 입력 줄에 대해 두 번째 필드의 값을 연관 배열에 저장합니다 a
(첫 번째 필드를 배열의 키로 사용). 해당 키 의 값 false
을 아직 저장하지 않은 경우 에만 해당 합니다 . ,
입력 및 출력 필드 구분 기호에 모두 사용하십시오 . 모든 입력 라인을 읽은 후 배열을 인쇄하십시오.
$ awk -F, -v OFS=, 'a[$1] != "false" { a[$1] = $2 };
END { for (i in a) {print i,a[i]} }' truefalse.txt
AA,false
BB,false
CC,false
DD,true
이 버전과 DopeGhoti 버전의 중요한 차이점은이 버전은의 값에 전혀 관심이없고의 값 $2
에만 관심이 있다는 것입니다 a[$1]
.
답변
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
패스