Sắp xếp các khối dòng


12

Tôi có một tập tin chứa 4n dòng. Đây là một đoạn trích từ nó chứa 8 dòng

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

Những gì tôi muốn làm là sắp xếp một khối, trong đó mỗi khối bao gồm 4 dòng dựa trên cột đầu tiên. Đầu ra cho đoạn trích sẽ trông như dưới đây.

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

Câu trả lời:


17

Một tùy chọn là sử dụng để thêm tiền tố số sê-ri ban đầu cho mỗi N dòng (N = 4 trong trường hợp của bạn). Sau đó nạp tiền tố làm cột sắp xếp chính vào sort.

Ví dụ với N = 4:

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

7

Nếu đây là một lần tắt và bạn không muốn học python, perl hoặc awk, bạn có thể đi với các lệnh cơ bản splitsortlệnh.

Đầu tiên chia tệp thành 4 dòng với -l tùy chọn:

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_*

Các sort -nsắp xếp theo giá trị số của cột đầu tiên (999 trước 1234). -a 6nên chăm sóc một tập tin với 26 ^ 6 * 4 dòng. my_prefix_nên là một cái gì đó độc đáo cho thư mục bạn làm việc với.


3

Bạn có thể làm điều đó với 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

Làm thế nào điều này hoạt động

  • -n-> chạy mã cho từng dòng đầu vào (và đặt dòng hiện tại vào $_)
  • -l -> nối một dòng mới vào đầu ra của bất kỳ print
  • -e -> thực thi chuỗi sau dưới dạng mã Perl
  • Mỗi dòng được gắn vào mảng @a.
  • $.giữ số dòng hiện tại và trừ khi số đó không đồng nhất với số 0 modulo 4, thì chúng tôi tiếp tục làm việc. Nếu nó đồng dư với zero modulo 4, chúng tôi đã đạt đến một dòng có số là bội số của 4 (cuối của một khối), trong trường hợp này, chúng tôi phân loại các mục trong @atrong thứ tự tăng dần số và in các mục trong mảng được sắp xếp tham gia bởi một dòng mới đến đầu ra tiêu chuẩn.

2

Sử dụng vỏ giống như 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

Dưới đây là một số awkgiải pháp "thuần túy" :

Nếu các chỉ mục luôn luôn là một chuỗi số nguyên tăng dần (6115-6119), như trong dữ liệu mẫu của bạn, bạn có thể sử dụng một "phím tắt" thuật toán:

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

Cái này không

  • Thêm tất cả các dòng vào mảng a, được phân phối tại các vị trí chỉ mục 6115-6119
  • Trên mỗi dòng thứ 4 ( !(NR%4)), lặp qua các nội dung mảng để in theo thứ tự mong muốn.

Nếu các chỉ mục số của bạn luôn là bốn chỉ số giống nhau, nhưng không phải là một chuỗi số nguyên tăng dần, bạn sẽ phải sắp xếp:

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

Lưu ý: Đây là với GNU awk, những người khác có thể không hỗ trợ asort.


Nếu mỗi khối bốn có thể có ID số khác nhau:

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

Lưu ý: TIL từ @Gilles tự trả lời (+2) việc sử dụng deletenày không phải (chưa) POSIX, nhưng được hỗ trợ phổ biến .


Phiên bản có sử dụng ™ chính xác delete:

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

Một phiên bản không xóa, sử dụng nhiều bộ nhớ và kích thước hơn:

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

1

Bạn có thể nhận được một giải pháp sạch với R. Nếu bảng trên nằm trong một tệp có tên là "table.txt", thì hãy thực hiện các bước sau. Kết quả mong muốn sẽ có trong tệp "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)

Xem thêm Làm thế nào để sắp xếp một dataframe theo cột (s) trong R .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.