Sắp xếp một phần của tập tin


8

Có thể sắp xếp giữa hai chuỗi trong một tệp lớn?

ví dụ: tập tin hiện tại là:

    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

Và đầu ra mong muốn là:

    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

Tại đây, Phần HUT 03 Điều khiển VRĐiều khiển thể thao HUT 04 được sắp xếp.

Trong tệp đã cho, các tiêu đề Phần bắt đầu bằng các ký tự không phải khoảng trắng trong khi nội dung của phần luôn bắt đầu bằng dấu cách hoặc tab. Vì tệp này có hơn 100 phần nên sẽ không khả thi với tên phần mã cứng trong tập lệnh / lệnh


Là các phần trên số dòng cố định, hoặc được xác định bởi các mẫu?
Sparhawk

Các tiêu đề của phần bắt đầu như một ký tự đầu tiên của dòng, trong khi nội dung của nó bắt đầu bằng dấu cách / tab. Các phần không nằm trên số cố định.
SHW

Bạn có muốn chỉ sắp xếp một phần (theo tiêu đề của câu hỏi và văn bản), hoặc mỗi phần không?
Kusalananda

@Kusalananda Tôi đồng ý câu hỏi không rõ ràng về điểm này; tuy nhiên đầu ra ví dụ hiển thị tất cả các phần (hoặc các phần của chúng) đang được sắp xếp.
Stephen Kitt

Tôi sẽ không nói rằng "HUT" sử dụng các ký tự hex.
jlliagre

Câu trả lời:


7

Trong 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 = "")

Điều này sắp xếp tất cả các phần (riêng biệt), không chỉ những phần giữa hai dòng cụ thể.


Tuyệt vời! Đây là chủ lực.
SHW

6

Để giải trí, đây là một cách để sắp xếp một phần bằng cách sử dụng ex:

ex file <<%
/HUT
+1,/HUT/-1!sort
w file.sorted
q
%

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

Điều này sử dụng awkđể thêm một số (và một dấu phân cách tab) phía trước mỗi dòng tương ứng với phần mà dòng này nằm trong. Đối với các tiêu đề của phần, chúng tôi thêm một số theo sau là một ký tự backspace (chỉ vì backspace sắp xếp trước các tab). Sau đó, chúng tôi chỉ cần sắp xếp dữ liệu kết quả trên các số này trước khi xóa chúng và các dấu tách tab được thêm vào.

Tiêu đề phần được phát hiện bằng cách tìm kiếm các ký tự không trống ở đầu dòng.


1
Đẹp! Tôi đặc biệt thích thủ thuật backspace.
Stephen Kitt

1
Với phương pháp này, bạn cũng có thể sử dụng số phần (sau HUTtrường) làm tiền tố, để sắp xếp các phần quá.
Stephen Kitt

3

Bạn có thể nhận được awksorthợp tác để hoàn thành công việc.

awk '
    /^[[:blank:]]/{print | "sort"; next}
    {close("sort"); print}; 
    END{close("sort")}
' file
  • Ống từng dòng nội dung vào sort
  • Gọi closetrên sortkhi một điểm đánh dấu phần là gặp phải; điều này gây ra sortviệc tuôn ra đầu ra của nó thành đầu ra tiêu chuẩn và thoát
  • In phần đánh dấu
  • Một phiên bản mới của phần sorttiếp quản cho các dòng nội dung theo phần đánh dấu phần
  • Gọi closevào sortcuối để chăm sóc nội dung

1

Đối với những nhiệm vụ như vậy tôi thường thấy tẻ nhạt khi viết kịch bản. Nếu nó chỉ cần được thực hiện một lần và có thể cho một vài tệp, nó có thể được thực hiện khá độc đáo bằng cách sử dụng macro nếu bạn mở tệp trong vimvà gõ:

  • GoFAKE SECTION<ESC>: thêm phần giả mạo vào cuối và đảm bảo rằng phần này nằm ở đầu dòng (bạn có thể có cindenthoặc autoindentbật). Điều này là cần thiết để sắp xếp phần cuối cùng là tốt.
  • gg: quay lại phần bắt đầu của tệp, sau đó tệp bắt đầu bằng một phần đi xuống một dòng với j
  • qq: bắt đầu ghi một macro để đăng ký q
  • v: bắt đầu lựa chọn
  • /^\S\+<Enter>: tìm kiếm phần đầu của phần tiếp theo
  • k: lên một dòng
  • :!sort<Enter: sắp xếp phần
  • nj: đi đến phần tử đầu tiên của phần tiếp theo
  • q: dừng ghi macro
  • @q: lặp lại macro
  • 100@@: lặp lại macro một vài lần (cho đến khi không còn phần nào)
  • dd: xóa dòng cuối cùng của tệp (the FAKE SECTION)

Bạn có thể muốn :set lazyredrawtăng tốc độ thực hiện macro.

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.