선 블록 정렬


12

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 

답변:


16

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

N = 4 인 예 :

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

7

이것이 꺼져 있고 파이썬, perl 또는 awk를 배우고 싶지 않다면 기본 splitsort명령 을 사용할 수 있습니다 .

먼저 다음 -l 옵션을 사용 하여 파일을 4 행 청크로 분할하십시오 .

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.
  • $.현재 줄 번호를 유지하고 그 번호가 모듈로 4와 일치하지 않는 한 계속 작동합니다. 이 경우 이고 영 모듈러스 4 합동, 우리는 그 번호 4 (블록의 종단)의 배수 인 라인,이 경우에, 우리는 분류 항목에 도달 한 @a수치의 승순과의 정렬 된 배열의 항목을 인쇄 개행으로 표준 출력에 결합됩니다.

2

Bourne과 같은 쉘을 사용하여

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data

2

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

인덱스가 항상 샘플 데이터에서와 같이 증분 정수 시퀀스 (6115-6119)와 동일한 경우 알고리즘 "바로 가기"를 사용할 수 있습니다.

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

이것은 않습니다

  • a인덱스 위치에 분포 된 모든 행을 배열에 추가합니다. 6115-6119
  • 4 번째 줄 ( !(NR%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}'

참고 : @Gilles self-answer (+2)의delete TIL은 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++}

1

R로 깨끗한 솔루션을 얻을 수 있습니다. 위의 테이블이 "table.txt"라는 파일에 있으면 다음 단계를 수행하십시오. 원하는 결과는 "tableout.txt"파일에 있습니다.

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

R의 열을 기준으로 데이터 프레임을 정렬하는 방법 도 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.