행에서 고유하게 정렬

행에서 고유하게 정렬

행에서 고유한 정렬을 수행하는 방법을 제안해 주실 수 있나요? 나는 다음 정보를 가지고 있습니다:

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.
  • -lRSto newlineORSto 도 설정됩니다 newline.
  • -aFS각 레코드는 선택 항목 에 따라 자동으로 단어로 분할됩니다 -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

관련 정보