행 블록 정렬

행 블록 정렬

4n줄이 포함된 파일이 있습니다. 다음은 8줄의 내용을 발췌한 것입니다.

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

내가 하고 싶은 것은 첫 번째 열을 기준으로 각 블록이 4개의 행으로 구성된 블록을 정렬하는 것입니다. 발췌문의 출력은 다음과 같아야 합니다.

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 

답변1

한 가지 옵션은 다음을 사용하는 것입니다.N 줄마다 초기 시퀀스 번호 접두사를 추가합니다(귀하의 경우 N=4). 그런 다음 에 기본 정렬 열로 접두사를 입력합니다 sort.

N=4의 예:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '

답변2

이것이 일회성이고 Python, Perl 또는 awk를 배우고 싶지 않다면 기본 splitsort명령을 배울 수 있습니다.

먼저 다음 옵션을 사용하여 파일을 4줄 청크로 분할합니다 -l .

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

sort -n첫 번째 열의 값(1234 이전의 999)을 기준으로 정렬합니다. -a 626^6*4 라인의 파일을 처리해야 합니다. my_prefix_사용 중인 디렉토리에 고유한 것이어야 합니다.

답변3

Perl을 사용하여 이 작업을 수행할 수 있습니다.

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

어떻게 작동하나요?

  • -n--> 각 입력 라인에 대해 코드를 실행합니다(그리고 현재 라인을 에 넣습니다 $_).
  • -l--> 모든 출력에 줄바꿈을 추가합니다.print
  • -e--> 다음 문자열을 Perl 코드로 실행
  • 각 행은 배열에 추가됩니다 @a.
  • $.현재 줄 번호를 저장합니다. 줄 번호가 0 모듈로 4와 같지 않으면 작업을 계속합니다. 그 경우0 모듈로 4와 일치하면 숫자가 4의 배수(블록 끝)인 행에 도달합니다. 이 경우 @a항목을 오름차순으로 정렬하고 줄 바꿈 문자로 연결된 정렬된 배열의 항목을 표준에 인쇄합니다. 산출.

답변4

다음은 "순수한" awk솔루션입니다.

예제 데이터에 표시된 것처럼 인덱스가 항상 동일한 증가 순서(6115-6119)인 경우 알고리즘 "단축키"를 사용할 수 있습니다.

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

이것은 실제로

  • a인덱스 위치 6115-6119에 분산된 배열에 모든 행을 추가합니다.
  • 4줄( )마다 !(NR%4)배열 내용을 반복하여 원하는 순서로 인쇄합니다.

숫자 인덱스가 항상 동일한 4개의 인덱스이지만 증가하는 정수 시퀀스가 ​​아닌 경우 다음과 같이 정렬해야 합니다.

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

참고: 이는 GNU awk용이므로 다른 사용자는 이를 지원하지 않을 수 있습니다 asort.


4개의 블록이 각각 다른 숫자 ID를 가질 수 있는 경우:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

참고: TIL은 다음에서 유래합니다.@Gilles 자체 답변(+2) 이 사용법은 delete아직 POSIX가 아니지만 일반적으로 지원됩니다..


사용할 올바른™ 버전 delete:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

더 많은 메모리와 크기를 사용하여 제거되지 않은 버전:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}

관련 정보