Sortir bagian file

8

Apakah mungkin untuk mengurutkan antara dua string dalam file besar?

mis. File saat ini adalah sebagai:

    0cf  Front Brake
    0d0  Rear Brake
    0ce  Handle Bars
HUT 03  VR Controls
    009  Vest
    001  Belt
    002  Body Suit
    020  Stereo Enable
    003  Flexor
    007  Hand Tracker
    004  Glove
    006  Head Mounted Display
    008  Oculometer
    00a  Animatronic Device
    000  Unidentified
    021  Display Enable
    005  Head Tracker
HUT 04  Sport Controls
    000  Unidentified
    002  Golf Club
    001  Baseball Bat

Dan output yang diinginkan adalah:

    0ce  Handle Bars
    0cf  Front Brake
    0d0  Rear Brake
HUT 03  VR Controls
    000  Unidentified
    001  Belt
    002  Body Suit
    003  Flexor
    004  Glove
    005  Head Tracker
    006  Head Mounted Display
    007  Hand Tracker
    008  Oculometer
    009  Vest
    00a  Animatronic Device
    020  Stereo Enable
    021  Display Enable
HUT 04  Sport Controls
    000  Unidentified
    001  Baseball Bat
    002  Golf Club

Di sini, Bagian HUT 03 Kontrol VR dan Kontrol Olahraga HUT 04 diurutkan.

Dalam file yang diberikan, Header bagian dimulai dengan karakter non-spasi sementara konten bagian selalu dimulai dengan spasi atau tab. Karena file ini memiliki 100+ bagian maka tidak akan layak untuk nama bagian hard-code dalam skrip / perintah

SHW
sumber
Apakah bagian pada nomor telepon tidak bergerak, atau ditentukan oleh pola?
Sparhawk
Header bagian dimulai sebagai karakter pertama dari baris, sedangkan isinya dimulai dengan spasi / tab. Bagian tidak pada nomor tetap.
SHW
Apakah Anda ingin mengurutkan satu bagian saja (sesuai judul pertanyaan dan teks), atau setiap bagian?
Kusalananda
@ Kusalananda Saya setuju bahwa pertanyaan ini tidak jelas tentang hal ini; contoh output bagaimanapun menunjukkan semua bagian (atau bagiannya) sedang diurutkan.
Stephen Kitt
Saya tidak akan mengatakan bahwa "HUT" menggunakan karakter hex.
jlliagre

Jawaban:

7

Dengan Python:

#!/usr/bin/python3

with open("file.txt", "r") as ins:
    lines = []
    for line in ins:
        if line.startswith((" ", "\t")):
            lines.append(line)
        else:
            lines.sort()
            print(*lines, end = "", sep = "")
            print(line, end = "")
            lines = []
    lines.sort()
    print(*lines, end = "", sep = "")

Ini mengurutkan semua bagian (secara terpisah), tidak hanya di antara dua baris tertentu.

Stephen Kitt
sumber
Hebat! Ini adalah masterstroke.
SHW
6

Untuk bersenang-senang, berikut adalah cara untuk mengurutkan satu bagian menggunakan ex:

ex file <<%
/HUT
+1,/HUT/-1!sort
w file.sorted
q
%
Jlliagre
sumber
6
$ awk 'BEGIN { OFS="\t"; s=0 } /^[^[:blank:]]/ { print ++s "\b", $0; next } { print s, $0 }' file | sort -n | cut -f 2-
    0ce  Handle Bars
    0cf  Front Brake
    0d0  Rear Brake
HUT 03  VR Controls
    000  Unidentified
    001  Belt
    002  Body Suit
    003  Flexor
    004  Glove
    005  Head Tracker
    006  Head Mounted Display
    007  Hand Tracker
    008  Oculometer
    009  Vest
    00a  Animatronic Device
    020  Stereo Enable
    021  Display Enable
HUT 04  Sport Controls
    000  Unidentified
    001  Baseball Bat
    002  Golf Club

Ini digunakan awkuntuk menambahkan angka (dan pemisah tab) di depan setiap baris yang sesuai dengan bagian di mana baris ini berada. Untuk header bagian, kami menambahkan angka diikuti oleh karakter backspace (hanya karena backspace mengurutkan sebelum tab). Kemudian kita cukup mengurutkan data yang dihasilkan pada angka-angka ini sebelum menghapusnya dan pemisah tab yang ditambahkan.

Header bagian dideteksi dengan mencari karakter yang tidak kosong di awal baris.

Kusalananda
sumber
1
Bagus! Saya terutama menyukai trik backspace.
Stephen Kitt
1
Dengan pendekatan ini Anda juga bisa menggunakan nomor bagian (setelah HUTbidang) sebagai awalan, untuk mengurutkan bagian juga.
Stephen Kitt
3

Anda bisa mendapatkan awkdan sortbekerja sama untuk menyelesaikan pekerjaan.

awk '
    /^[[:blank:]]/{print | "sort"; next}
    {close("sort"); print}; 
    END{close("sort")}
' file
  • Pipa setiap baris konten ke sort
  • Panggil closepada sortsaat bagian penanda ditemui; ini menyebabkan sortflush outputnya ke output standar dan keluar
  • Cetak penanda bagian
  • Contoh baru dari sortpengambilalihan untuk baris konten mengikuti penanda bagian
  • Panggil closepada sortdi akhir untuk mengurus konten membuntuti
iruvar
sumber
1

Untuk tugas-tugas seperti itu, saya sering merasa bosan untuk menulis naskah. Jika hanya perlu dilakukan sekali dan mungkin untuk beberapa file, itu bisa dilakukan dengan cukup baik menggunakan makro jika Anda membuka file vimdan ketik:

  • GoFAKE SECTION<ESC>: tambahkan bagian palsu di bagian akhir, dan pastikan ini ada di awal baris (Anda mungkin telah cindentatau autoindentdiaktifkan). Ini diperlukan untuk menyortir bagian terakhir juga.
  • gg: kembali ke awal file, lalu file dimulai dengan bagian turun satu baris dengan j
  • qq: mulai merekam makro untuk mendaftar q
  • v: mulai seleksi
  • /^\S\+<Enter>: cari awal bagian selanjutnya
  • k: naik satu baris
  • :!sort<Enter: urutkan bagian
  • nj: buka elemen pertama dari bagian selanjutnya
  • q: berhenti merekam makro
  • @q: ulangi makro
  • 100@@: ulangi makro beberapa kali (sampai tidak ada bagian yang tersisa)
  • dd: hapus baris terakhir file (the FAKE SECTION)

Anda mungkin ingin :set lazyredrawmempercepat eksekusi makro.

MarcDefiant
sumber