비슷한 파일이 있습니다.
HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
TR|17
각 청크에 대한 BH 레코드의 두 번째 필드를 기준으로 청크를 정렬해야 합니다. 블록 내의 행은 그대로 유지되어야 합니다. 위 파일의 예상 출력은 다음과 같습니다.
HR|testing file
**BH|100**
B2|cat|10
B2|dog|20
BT|4
**BH|102**
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
**BH|105**
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
답변1
이는 #
블록 BH|#
헤더 행을 기준으로 오름차순으로 BH|100
각 BH|102
블록을 BH|105
정렬 하고 작동해야 합니다 ...
.
awk -v RS='BH|TR' 'NR>1{ seen[NR]=$0; next } { printf $0 }
END{ TR="TR"seen[NR]; delete seen[NR]; asort(seen);
for(x in seen) printf "BH"seen[x]; printf TR }' infile
HR|testing file
BH|100
B2|cat|10
B2|dog|20
BT|4
BH|102
B2|fan|10
B2|bulb|20
B2|washer|10
B2|dryer|10
BT|6
BH|105
B2|apple|10
B2|banana|20
B2|melon|10
BT|5
TR|17
이는
RS='BH|TR'
레코드 구분 기호(기본적으로 ewline)로 및 를 정의합니다.BH
TR
\n
이 블록은
NR>1{ seen[NR]=$0; next }
모든 사람에게 실행됩니다.오른쪽로깅하지만 먼저NR
(질소수량오른쪽레코드) 따라서 연관 배열의 키(인덱스)인 각 레코드 번호에 대해 호출됩니다.본전체 레코드의 값이 여기에 설정되고next
레코드가 읽혀집니다.- 첫 번째 기록이 아닌 경우
{ printf $0 }
그것. 다음 번에는 이기 때문에 이것은 한 번만 실행됩니다NR>1
.
마지막으로 블록이 END{ ... }
실행되고 다음을 수행합니다.
- 그러면
TR="TR"seen[NR]
배열의 마지막 레코드가 복사되어 이름이 지정된 변수에 삽입됩니다.TR그런 다음 배열에서 제거합니다delete seen[NR]
. - 이렇게
asort(seen)
하면 배열이 정렬됩니다.본저장된 값을 기반으로 합니다. for(x in seen)
우리는 이 배열을 반복 하고printf "BH"seen[x]
- 마지막으로 복사한 내용을 인쇄합니다.TR.
파일의 첫 번째 줄과 마지막 줄이 마음에 들지 않으면 다음과 같이 할 수도 있습니다.
sed '1d; $d' infile |awk '{printf $0(/^BT/?"\n":"#")}' |sort |tr '#' '\n'
답변2
나는 이 작업을 수행하는 빠르고 쉬운 방법을 찾았습니다. 더 좋은 방법이 있으면 제안해주세요.
헤더 및 트레일러 레코드가 제거되었습니다. 블록의 줄 사이에 줄 구분 기호로 #을 병합하고 넣어서 한 줄로 병합합니다. 특정 필드별로 정렬새 줄로 바꾸기#
gawk '/^HC/ && line {print line; line=""} {line = line ? line"#"$0 : $0} END {print line}' input.txt | sort -t"|" -nk 13 | tr '#' '\n' > finaloutput.txt