두 번째 필드를 기준으로 정렬한 다음 동일한 첫 번째 열을 사용하여 행을 다시 정렬하지만 각 그룹에 대해 두 번째 필드의 순서는 계속 유지합니다.

두 번째 필드를 기준으로 정렬한 다음 동일한 첫 번째 열을 사용하여 행을 다시 정렬하지만 각 그룹에 대해 두 번째 필드의 순서는 계속 유지합니다.

파일을 정렬하고 싶습니다.

입력하다:

I1, -2   
I2, -6  
I2, -9  
I1, -8  
I1, -1  
I3, -7  
I2, -4  
I3, -4  

산출:

I2, -9  
I2, -6  
I2, -4  
I1, -8  
I1, -2  
I1, -1  
I3, -7  
I3, -4

아래 출력을 어떻게 얻을 수 있습니까?

답변1

더러운 해결책은 다음과 같습니다.

<infile sort -t, -rk2,2 \
|awk -F, '{ seen[$1]= (seen[$1]==""? "\0":seen[$1] ORS) $0 }
 END{ for (x in seen) print seen[x] }' \
|sort -z -t, -rk2,2 \
|tr -d '\0'

분해:

  • <infile sort -t, -rk2,2
    그러면 r입력 파일이 역순으로 정렬 됩니다.infile두 번째 필드(쉼표는 구분 기호)는 key 필드 역할을 합니다.

  • 이것코드는 단순히 동일한 첫 번째 열로 레코드를 재정렬하여 각 그룹을 구분합니다.유효하지 않은특징 \0.

  • sort -z -t, -rk2,2
    -z이 역방향 정렬은 두 번째 필드와 쉼표로 구분된 필드(널 문자로 구분, Tell-sort 명령 사용)에서 이러한 블록을 정렬합니다. 이 단계를 실행하기 전에 다음 출력을 검토하고 cat -A표시되는 내용을 추가하세요.

    ^@I1, -8$
    I1, -2$
    I1, -1$
    ^@I2, -9$
    I2, -6$
    I2, -4$
    ^@I3, -7$
    I3, -4$
    

    ^@문자는 널 문자를 나타냅니다. sort -z위 입력은 다음과 같습니다(사람의 가독성과 이해를 돕기 위해 이렇게 했습니다).

    ^@I1, -8$      I1, -2$      I1, -1$
    ^@I2, -9$      I2, -6$      I2, -4$
    ^@I3, -7$      I3, -4$
    

    당신은 아이디어를 얻었습니다. 위의 정렬 명령은 두 번째 필드를 다음과 같이 봅니다.

     -8$      I1
     -9$      I2
     -7$      I3
    

    ...이를 역순으로 정렬하면 결과는 다음과 같이 변경됩니다.

    ^@I2, -9$      I2, -6$      I2, -4$
    ^@I1, -8$      I1, -2$      I1, -1$
    ^@I3, -7$      I3, -4$
    

    ...구조체를 반환하면 실제로 다음과 같은 결과가 나타납니다.

    ^@I2, -9$
    I2, -6$
    I2, -4$
    ^@I1, -8$
    I1, -2$
    I1, -1$
    ^@I3, -7$
    I3, -4$
    
  • tr -d '\0'
    결과에서 추가된 널 문자가 제거되고 최종 출력은 다음과 같습니다.

    I2, -9
    I2, -6
    I2, -4
    I1, -8
    I1, -2
    I1, -1
    I3, -7
    I3, -4
    

답변2

GNU 사용 awk:

gawk '
  grp[$1] == "" || $2 < grp[$1] { grp[$1] = $2 }
  { val[$1][$2] }
  END {
    PROCINFO["sorted_in"] = "@val_num_asc"
    for (i in grp) {
      PROCINFO["sorted_in"] = "@ind_num_asc"
      for (j in val[i]) print i,j
    }
  }' ./file

아이디어는 다음과 같습니다.

  • grp배열에 있는 열 1의 각 고유 값에 대해 열 2의 최소값을 저장합니다.
  • 각 행을 2D 배열에 저장하면 열 1의 각 고유 값에 대해 열 2의 값을 쉽게 검색할 수 있습니다( 데이터의 원래 간격을 유지하고 사용할 val수도 있음 ).val[$1][$2] = $0print val[i][j]
  • 해당 요소의 값을 기준으로 배열을 반복 PROCINFO["sorted_in"]하고 해당 인덱스 값을 기준으로 (항상 오름차순으로 정렬) (단일) 배열을 반복하는 데 사용됩니다. 열 2와 동일한 최소값을 공유하는 열 1 값의 정렬 순서를 변경하려는 경우(예: 샘플 데이터에 추가하고 출력하기 전에 정렬하려는 경우) 직접 정의해야 할 수도 있습니다. 정렬 기능) .grpval[i]
    I4, -9I4I2

다음을 기반으로 하는 휴대용 대안슈워츠 변환, 아마도:

sort -k2,2n ./file |
  awk '
    grp[$1] == "" { grp[$1] = $2 }
    { print grp[$1] "," $0 }' |
  sort -t, -k 1,1n -k 2,2 -k 3,3n |
  cut -d, -f2-

여기서 "그룹당"(즉, 열 1의 값에 상대적) 열 2의 최소값은 각 행의 앞에 추가되어 각 그룹( -9, -8, -7)의 최소값을 기준으로 후속 정렬이 가능합니다. 열 1(그룹화된 행을 유지하기 위해), 열 2의 값은
awk정렬된 데이터를 제공하여 스크립트를 더 간단하게 만듭니다. 각 행에 대해 행이 충족될 때 각 그룹의 최소값이 이미 알려져 있으므로 그럴 필요가 없습니다. 일부 구조 라인에 저장하고 END블록으로 인쇄합니다(또는 파일을 두 번 처리).

관련 정보