각 섹션의 첫 번째 줄에 있는 네 번째 값을 기준으로 파일 섹션을 정렬하는 방법은 무엇입니까?

각 섹션의 첫 번째 줄에 있는 네 번째 값을 기준으로 파일 섹션을 정렬하는 방법은 무엇입니까?

빈 줄로 구분된 여러 섹션이 있는 파일이 있는데, 각 섹션의 본문을 수정하지 않은 상태로 유지하면서 각 섹션의 첫 번째 줄의 네 번째 값을 기준으로 모든 섹션을 오름차순으로 정렬하고 싶습니다.

입력 예

PT2 energy =  7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 :  0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4  TDM-form-state 1=   0.2702   -0.2855  -0.5610 TDM= 0.69  f: 0.082

PT2 energy =  7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 :  0.352 (0.124)
22220ud0 5-->6,7 :  0.326 (0.106)
2222u0d0 5->7 :  0.303 (0.092)
2222u00d 5->8 :  0.271 (0.073)
222ud020 4,5-->7 :  0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5  TDM-form-state 1=   0.0860   -0.1785  -0.5446 TDM= 0.58  f: 0.058

PT2 energy =  6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6  TDM-form-state 1=  -0.2916   -0.0544  -2.1475 TDM= 2.17  f: 0.754

산출

PT2 energy =  6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6  TDM-form-state 1=  -0.2916   -0.0544  -2.1475 TDM= 2.17  f: 0.754

PT2 energy =  7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 :  0.352 (0.124)
22220ud0 5-->6,7 :  0.326 (0.106)
2222u0d0 5->7 :  0.303 (0.092)
2222u00d 5->8 :  0.271 (0.073)
222ud020 4,5-->7 :  0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5  TDM-form-state 1=   0.0860   -0.1785  -0.5446 TDM= 0.58  f: 0.058

PT2 energy =  7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 :  0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4  TDM-form-state 1=   0.2702   -0.2855  -0.5610 TDM= 0.69  f: 0.082

나는 전에 시도했다

sort -n -k4 file

하지만 이는 모든 파일에 대해 작동하고 이러한 부분을 파괴합니다.

답변1

awk, sort 및 cut을 사용하십시오.

$ awk -v OFS='\t' '!pNF{val=$4} {print val, NR, $0; pNF=NF} END{if (pNF) print val, NR+1, ""}' file |
    sort -k1,1n -k2,2n |
    cut -f3-
PT2 energy =  6.552 eV ( -459.6143027 au) ( 52841.3 cm-1) (R=6)
222u20d0 4->7 : -0.612 (0.374)
2222ud00 5->6 : -0.499 (0.249)
222udud0 4,5-->6,7 : -0.271 (0.074)
R=6  TDM-form-state 1=  -0.2916   -0.0544  -2.1475 TDM= 2.17  f: 0.754

PT2 energy =  7.018 eV ( -459.5971543 au) ( 56605.0 cm-1) (R=5)
22u220d0 3->7 : -0.396 (0.156)
222u2d00 4->6 :  0.352 (0.124)
22220ud0 5-->6,7 :  0.326 (0.106)
2222u0d0 5->7 :  0.303 (0.092)
2222u00d 5->8 :  0.271 (0.073)
222ud020 4,5-->7 :  0.267 (0.071)
22u22d00 3->6 : -0.229 (0.052)
R=5  TDM-form-state 1=   0.0860   -0.1785  -0.5446 TDM= 0.58  f: 0.058

PT2 energy =  7.135 eV ( -459.5928710 au) ( 57545.0 cm-1) (R=4)
22u22d00 3->6 : -0.535 (0.286)
22202200 4-->6 : -0.344 (0.119)
222u200d 4->8 :  0.256 (0.065)
222u2d00 4->6 : -0.254 (0.065)
R=4  TDM-form-state 1=   0.2702   -0.2855  -0.5610 TDM= 0.69  f: 0.082

그렇지 않으면 GNU awk를 사용하여 배열의 배열을 처리하고 sorted_in을 사용하십시오.

awk '
    BEGIN { RS=""; ORS="\n\n" }
    { recs[$4][++cnt[$4]] = $0 }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"
        for (val in recs) {
            for (i=1; i<=cnt[val]; i++) {
                print recs[val][i]
            }
        }
    }
' file

루프의 목적은 cnt[]동일한 값(예: 7.135)이 서로 다른 입력 레코드의 네 번째 필드에 여러 번 나타나는 경우 출력에서 ​​해당 키 값의 입력 순서를 유지하는 것입니다. 또는 입력을 읽을 때 문자열 연결을 통해 동일한 결과를 얻을 수 있습니다(예: 정렬을 위해 여전히 GNU awk를 사용).

awk '
    BEGIN { RS=""; ORS="\n\n" }
    { recs[$4] = recs[$4] $0 ORS }
    END {
        PROCINFO["sorted_in"] = "@ind_num_asc"
        for (val in recs) {
            printf "%s", recs[val]
        }
    }
' file

gawk 전용 접근 방식의 단점은 전체 파일을 메모리에 저장해야 하고 gawk가 없는 시스템으로 이식할 수 없다는 것입니다. 상단의 awk+sort+cut 스크립트는 이식성이 뛰어나고 "정렬"만 전체 파일을 한 번에 처리해야 하며 요구 페이징 등을 사용하여 대용량 파일을 처리하도록 설계되었으므로 그보다 큰 파일을 처리할 가능성은 거의 없습니다. 멍하니 질문.

답변2

sort라인 중심입니다. 여기에서 "단락"의 파일을 읽어야 합니다.

이는 매우 짧은 GNU awk 프로그램을 사용하여 수행할 수 있습니다.

gawk -v RS= -v ORS='\n\n' '
  {section[$4] = $0}
  END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (key in section) print section[key]
  }
' file

RS 변수(레코드 구분자)를 빈 문자열로 설정하면 빈 줄로 구분된 레코드가 포함된 파일을 읽습니다. 각 레코드는 배열에 저장되고 정렬 키로 인덱싱됩니다.

마법의 PROCINFO 라인은 gawk에게 배열을 반복할 때 인덱스별로 배열을 숫자로 정렬하라고 지시합니다.

관련 정보