การเรียงบล็อกของเส้น


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

ถ้านี่เป็นการปิดและคุณไม่ต้องการเรียนรู้ python, perl หรือ awk คุณสามารถไปกับพื้นฐานsplitและsortคำสั่ง

ก่อนแบ่งไฟล์เป็น 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ทุกประเภทโดยค่าตัวเลขของคอลัมน์แรก (999 ก่อน 1234) -a 6ควรดูแลไฟล์ที่มี 26 ^ 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 เราจะทำงานต่อไป ถ้ามันเป็นความสอดคล้องกับศูนย์ modulo 4 เราได้มาถึงบรรทัดที่มีจำนวนเป็นหลาย 4 (ตอนจบของบล็อกที่) ซึ่งในกรณีนี้เราเรียงลำดับรายการใน@aในเรียงลำดับตัวเลขและพิมพ์รายการในแถวเรียง เข้าร่วมโดยขึ้นบรรทัดใหม่ไปยังเอาต์พุตมาตรฐาน

2

ใช้เปลือกคล้ายบอร์น

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อาจไม่สนับสนุน


หาก block-of-Four ทุกตัวอาจมี 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++}

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)

ดูเพิ่มเติมวิธีการเรียงลำดับ dataframe โดยคอลัมน์ (s) ในการวิจัย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.