빈 줄로 구분된 여러 섹션이 있는 파일이 있는데, 각 섹션의 본문을 수정하지 않은 상태로 유지하면서 각 섹션의 첫 번째 줄의 네 번째 값을 기준으로 모든 섹션을 오름차순으로 정렬하고 싶습니다.
입력 예
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에게 배열을 반복할 때 인덱스별로 배열을 숫자로 정렬하라고 지시합니다.