.tsv
Linux 시스템에 다양한 유형(문자열, 숫자)의 쉼표로 구분된 값을 포함하는 다음 열이 포함된 (탭으로 구분된 열) 파일이 있습니다 .
col1 col2
. NS,NS,NS,true,true
. 12,12,12,13
1,1,1,2 door,door,1,1
고유한 가치를 유지하고 싶습니다(아쉽게도 시도했지만 실패했습니다). 출력은 다음과 같습니다.
col1 col2
. NS,true
. 12,13
1,2 door,1
답변1
이는 값 문자열을 정수 인덱스 맵으로 분할한 다음 결합하는 Miller 변형입니다.열쇠쉼표로 구분된 문자열로 돌아가기):
mlr --tsv put 'for (k,v in $*) {
$[k] = joink(apply(splitnvx(v,","), func(k,v) {return{v:k}}),",")
}' file.tsv
또는 perl5의 도움으로목록::유틸리티기준 치수:
perl -MList::Util=uniq -F'\t' -lpe '
$_ = join "\t", map { join ",", uniq split /,/, $_ } @F
' file.tsv
답변2
사용밀러( mlr
)는 각 입력 레코드의 탭으로 구분된 필드를 반복하고, 필드 값을 쉼표로 분할하고, 각 결과 문자열을 명명된 맵의 키로 추가하고, 마지막으로 seen
재정의할 구분 기호로 쉼표를 사용하여 맵을 연결합니다. 필드 seen
:
$ mlr --tsv put 'for (k,v in $*) { seen={}; for (i in splitax(v,",")) { seen[i]=1 } $[k] = joink(seen,",") }' file
col1 col2
. NS,true
. 12,13
1,2 door,1
Miller의 put
표정이 아름답게 인쇄되어 있습니다.
for (k, v in $*) {
seen = {};
for (i in splitax(v, ",")) {
seen[i] = 1
}
$[k] = joink(seen, ",")
}
분할 값을 맵의 키로 추가하면 중복이 제거됩니다. 이 splitax()
함수는 각 결과 항목의 유형을 추론하지 않고 구분 기호의 문자열을 배열로 분할합니다(문자열이 됩니다). 이 joink()
함수는 맵의 키를 함께 연결하여 지정된 구분 기호로 구분된 문자열을 형성합니다. 외부 루프의 k
합계 값은 v
각각 필드 이름과 해당 값입니다.
답변3
투박한 Perl 접근 방식은 다음과 같습니다.
$ perl -F'\t' -le '
%k=%l={};
print join("\t",
join(",",grep{++$k{$_}==1}split(/,/,$F[0])),
join(",",grep{++$l{$_}==1}split(/,/,$F[1]))
)' file.tsv
col1 col2
. NS,true
. 12,13
1,2 door,1
답변4
다음 프로그램이 수행됩니다( 배열 (1)awk
작업을 지원 하는 모든 최근 Awk 구현 과 함께 작동해야 함):delete
BEGIN{FS=OFS="\t"}
{
for (i=1;i<=NF;i++)
{
n=split($i,sf,",")
delete seen
fld=""
for (j=1;j<=n;j++)
{
if (!seen[sf[j]]++)
{
fld=fld (fld?",":"") sf[j]
}
}
$i=fld
}
print
}
예를 들어 다음과 같이 저장 dedup.awk
하고 호출하세요.
awk -f dedup.awk input.tsv
입력 파일에 대해 작업하십시오.
그러면 \t
입력 및 출력 필드 구분 기호가 설정됩니다. 그러면 그럴 것이다
for (i=1;i<=NF;i++)
행의 모든 필드를 반복( )- 각 필드를 하위 필드로 분할(
sf
),
- 모든 하위 필드를 반복하고 필드를 임시 변수로 재조립
fld
하지만 아직 필드에 표시되지 않은 하위 필드 값만 추가합니다. 배열에 레코드를 저장합니다seen
. - 마지막으로 재조립된 필드를
fld
현재 필드에 할당합니다.$i
- 지금까지의 모든 수정 사항을 포함하여 전체 라인을 인쇄합니다.
(1) 요즘 지원이 꽤 널리 퍼져 있음을 암시해준 @EdMorton에게 감사드립니다.