행에서 고유한 정렬을 수행하는 방법을 제안해 주실 수 있나요? 나는 다음 정보를 가지고 있습니다:
Special c1,c2,c5,c7,c1,c2
Special2 C6
Special
(이것은 과 사이의 탭 문자입니다 c1...
.)
나는 다음과 같은 출력을 원합니다 :
Special c1,c2,c5,c7
Special2 C6
어떻게 해야 하나요?
답변1
사용이 답변,
perl -MList::MoreUtils=uniq -laF'\t' -ne '
$F[1] = join(",", uniq(sort(split(",", $F[1])))); print join("\t", @F)'
외부 패키지에 따라 다릅니다.목록::추가 유틸리티. 외부 종속성을 설치하지 않으려면 uniq
기능을 다시 구현하는 것이 좋습니다.Perl 코드 몇 줄. (macOS 기본 시스템의 일부로 설치한 것으로 보이지만)
답변2
perl -F'\t|,' -lane 'my %h; print shift @F, "\t", join ",", sort grep !$h{$_}++, @F' dataf
설명하다
-F'\t|,'
@F
=> 각 레코드 필드를TAB
또는 문자 배열 로 분할합니다comma
.-l
RS
tonewline
및ORS
to 도 설정됩니다newline
.-a
FS
각 레코드는 선택 항목 에 따라 자동으로 단어로 분할됩니다-F
.-n
루프 읽기에 대한 암시적 기록이 입력에 설정되어AND
요청될 때만 내용을 인쇄합니다.-e
위의 선택에 따라Perl
각 입력 레코드에 대해 실행되는 코드 입니다.RS
-l
- 첫 번째 요소가 제공되고
shift
나머지 요소는 레코드를 읽을 때마다 재생성되는uniquified
해시의 키로 저장하여 제공됩니다 .%h
그런 다음 고유한 요소를 정렬하고 쉼표로 연결하여 인쇄합니다.
답변3
OpenBSD awk
, GNU 및 다음을 사용하여 awk
테스트되었습니다 mawk
.
awk -F ',| +' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }' data.in |
sort -u |
awk '{ f[$1] = (f[$1] ? f[$1] "," : "") $2 } END { for (k in f) { print k, f[k] } }'
첫 번째는 awk
주어진 데이터를 다음으로 확장합니다.
Special c1
Special c2
Special c5
Special c7
Special c1
Special c2
Special2 C6
쉼표와 여러 공백을 필드 구분 기호로 사용하고 입력된 각 레코드(행)에 대해 첫 번째 필드를 별도의 줄에 순차적으로 인쇄한 다음 다른 모든 필드를 순차적으로 인쇄합니다. 이는 구분 기호로 올바르게 해석되는 위치 외에 줄에 추가 공백이나 쉼표가 없다고 가정합니다.
중간은 다음 sort
과 같이 정렬합니다.
Special2 C6
Special c1
Special c2
Special c5
Special c7
전체 행을 정렬 키로 사용하여 정렬하고 중복 행을 삭제합니다.
마지막으로 awk
데이터는 다음과 같이 재조립됩니다.
Special c1,c2,c5,c7
Special2 C6
첫 번째 필드를 연관 배열의 키로 사용하고 두 번째 필드에 해당 데이터를 쉼표로 구분하여 연결하여 값으로 저장함으로써 이를 수행합니다. 마지막으로 수집된 모든 데이터를 인쇄합니다.
답변4
또 다른 방법은 한 줄입니다.
while read line; do echo "$line" | awk '{print $1}' | tr '\n' ' '; echo "$line" | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',' | sed -e 's/.$//g'; echo; done < file_to_sort
각 행의 첫 번째 열( )을 가져와 echo $line | awk '{print $1}' | tr '\n' ' ';
두 번째 열 값을 ","로 구분하여 적용용 단일 열로 변환한 후 sort
다시 원래 형식( )의 단일 행으로 변환합니다 echo $line | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ','
.
@tripleee가 제안한 대로 줄 분할을 수행합니다.
while IFS=$'\t' read first second; do printf "%s\t%s\n" "$first" "$(tr ',' '\n' <<<"$second" | sort | tr '\n' ',' | sed -e 's/.$//g';)"; done < file_to_sort