Đánh số lại một danh sách khi một mục mới được chèn


6

Tôi có một tệp văn bản của các mục được đánh số:

1. foo
2. bar 100%
3. kittens
4. eat cake
5. unicorns
6. rainbows

và như vậy lên đến một số lượng lớn. Sau một dòng trống, một khối mới bắt đầu từ 1.

Tôi chèn một mục mới, thay thế, giả sử, 4. và tôi cần đánh số lại tất cả các mục tiếp theo trong khối:

1. foo
2. bar 100%
3. kittens
4. sunshine <
5. eat cake
6. unicorns
7. rainbows

2
Là các khối liền kề nhau, hoặc có một dải phân cách? (Ngay cả một dòng trống?)
Stephen Kitt

Câu trả lời:


5

Giải pháp VIM

Có hai giải pháp: một là thông qua tự động Ctrlanhấn phím qua một lựa chọn, thứ hai là thông qua thực hiện thay thế mẫu với submatch(0)+1hơn lựa chọn. Đầu tiên là tự động hóa chính.

Bắt đầu bằng cách tạo danh sách của bạn:

1. foo
2. bar 100%
3. kittens
4. eat cake
5. unicorns
6. rainbows

Chèn một mục

1. foo
2. bar 100%
3. kittens
4. eat cake
4. sunshine
5. unicorns
6. rainbows

Định vị con trỏ của bạn lên 4. sunshinevà từ chế độ lệnh nhấn shift+ v, sau đó shift+ g. Đây là lựa chọn trực quan cho đến cuối tập tin. Bạn cũng có thể di chuyển con trỏ đến cuối một khối theo những cách thông thường.

Nhấn :để vào chế độ lệnh và bạn sẽ thấy điều này : :'<,'> . Bây giờ gõ như sau:

norm Ctrl+ V Ctrl+A

Những gì Ctrl-v và ctrl-A làm, là chúng cho phép bạn nhập khóa "chính xác", do đó, nó sẽ thay đổi thành ^A, được tô sáng. Về cơ bản for all lines selected, execute in normal mode keypress Ctrl-A, điều này nói và Ctrl-A theo mặc định sẽ tăng số theo con trỏ. Bạn sẽ thấy những con số thay đổi

Giải pháp trong hành động:

Trước

nhập mô tả hình ảnh ở đây

Sau

nhập mô tả hình ảnh ở đây


Một cách khác là chọn mọi thứ từ số lặp lại đầu tiên như trước ( Shiftv, sau đó G) và chuyển sang chế độ lệnh để thực thi:

:'<,'>s/\v(^\d+)\./\=(submatch(0)+1).'.'/ 

Đây chính xác là câu trả lời dễ nhớ đơn giản mà tôi đang tìm kiếm và không thể tìm ra!
Zanna

Tôi không thể sử dụng / gõ Ctrl-A trong vim vì cntrl-A được ánh xạ tới khóa khác tmux. Có cách nào để gửi lệnh tương tự như ctrl-Avim qua chế độ lệnh vims không, vì vậy tôi không phải gõ ctrl-A?
alpha_989

@ alpha_989 Vâng, theo digitalronin.github.io/2016/06/28/vim-increment-column.html này loại anh chàng Ctrl-a a. Hoạt động của tôi cũng vậy :)
Sergiy Kolodyazhnyy

@ alpha_989 Tôi đã thêm một giải pháp chế độ lệnh khác. Điều đó tránh việc gõ Ctrl + hoàn toàn
Sergiy Kolodyazhnyy

13

Bạn luôn có thể thêm mục nhập mới của mình bằng x. newentrycú pháp và đánh số lại mọi thứ sau đó bằng một cái gì đó như:

awk -F . -v OFS=. '{if (NF) $1 = ++n; else n = 0; print}'
  • -F .: đặt dấu phân cách trường thành .1
  • -v OFS=.: tương tự cho dấu tách trường đầu ra ( -F .viết tắt của -v FS=.).
  • {...}: không có điều kiện nên mã bên trong {...}được chạy cho mỗi dòng
  • if (NF), nếu số lượng trường lớn hơn 0. Với FShiện tại ., điều đó có nghĩa là nếu dòng hiện tại chứa ít nhất một trường .. Chúng tôi cũng có thể làm cho nó if (length)để kiểm tra các dòng không trống.
  • $1 = ++n: đặt trường đầu tiên thành tăng n(ban đầu là 0, sau đó là 1, sau đó là 2 ...).
  • else n = 0: other (khi NF == 0) đặt lại n về 0.
  • print: in dòng (có thể sửa đổi).

1 Cú pháp là -F <extended-regular-expression>nhưng khi <extended-regular-expression>là một ký tự đơn, đó không được coi là một biểu thức thông thường ( .có nghĩa là bất kỳ ký tự nào) mà thay vào đó là ký tự đó.


đây là công việc cho tôi :) Tôi thích một số lời giải thích khi tôi là người mới bắt đầuawk
Zanna

@Zanna, xem chỉnh sửa.
Stéphane Chazelas

6

Mức tối đa quá mức (và độ phức tạp! Và lỗi!) Có thể có thông qua mô-đun Text :: Autoformat perl.

% < input                                                                    
1. foo
2. bar 100%
3. kittens
4. it is getting dark. there may be a grue
4. no seriously, it's getting dark
4. really, you should find a light or something.
4. are you even paying attention? helloooo
4. eat cake
5. unicorns
6. rainbows
% perl -MText::Autoformat -0777 -ple '$_=autoformat $_, { all => 1 }' < input
 1. foo
 2. bar 100%
 3. kittens
 4. it is getting dark. there may be a grue
 5. no seriously, it's getting dark
 6. really, you should find a light or something.
 7. are you even paying attention? helloooo
 8. eat cake
 9. unicorns
10. rainbows
% 

Kết quả thực tế sẽ phụ thuộc vào đầu vào, đầu ra mong muốn, các tùy chọn được thông qua, v.v.


3

Sử dụng các công cụ shell cơ bản, nó có thể được thực hiện như thế này - nó thậm chí có thể đơn giản hơn:

paste -d . <(seq $(wc -l < new.list)) <(cut -d . -f 2- < new.list) 

Tôi sẽ giải thích từ ngoài vào trong:

paste -d . file1 file2 

tạo các dòng đầu ra từ các tệp dưới dạng cột. -d .đặt dấu phân cách ., sẽ kết thúc đằng sau các số mới.

commandA <(commandB)

bắt đầu commandBvà trình bày kết quả đầu ra như thể nó là nơi để đọc tệp từ commandAđó, dự kiến ​​tên tệp là đối số. (Xem thay thế lệnh.)

Đối số thứ hai của paste ,, <(cut -d . -f 2- < new.list)xuất ra cột thứ hai không thay đổi, mỗi dòng từ trường thứ hai trở đi, có nghĩa là bắt đầu sau ..

Đối số đầu tiên của việc pastetạo các số dòng liên tiếp mới: đầu tiên nó đếm các dòng bằng cách sử dụng "dòng từ": $(wc -l < new.list)và sử dụng số này để tạo một chuỗi các số từ 1 đến số đếm, với seq 7.


Ồ, liên quan đến các dòng trống, điều đó đúng - tôi tập trung vào trường hợp thử nghiệm. Nhưng liên quan đến .- nó giả định rằng có số .sau; Sau đó, .một dòng không có hiệu lực, bởi vì sau đó dòng sẽ bị cắt ở dấu phân cách đầu tiên, trước trường 2, chỉ ( -f 2-có nghĩa là trường 2 và tiếp theo) - và không chạm vào các dấu phân cách tiếp theo không được sử dụng để cắt. Nó xử lý chúng như cổng của lĩnh vực. Về phần mới tách dòng, csplit(cũng từ coreutils) có vẻ đúng; Phân chia thô tại các dòng trống, áp dụng phương pháp trên, kết quả mèo với nhau. Cảm ơn đã chỉ ra điều đó!
Volker Siegel

@don_crissti Tôi thấy - ví dụ của OP không rõ về điều đó - Tôi đã xem ví dụ về @tring và bị đánh lừa bởi các 4., 4. 4.dòng liên tiếp . Hãy cùng xem ...
Volker Siegel

+1 rất hay cho khối đầu tiên (ví dụ như) ... Tôi cần chơi cùng pasteseqmột số thứ nữa ... Tôi có thể làm điều đó dễ dàng trong một trình soạn thảo đếm các dòng, nhưng tôi muốn một cách không bị phá vỡ nếu số tôi muốn chèn KHÔNG phải là số dòng> _ <
Zanna

1
Nếu bạn sử dụng vim, bạn có thể chạy lệnh từ vim trên các dòng được chọn - nếu chúng chỉ là số ít. (Một tập lệnh cần xử lý rằng đầu vào được đọc hai lần, sử dụng tệp tmp hoặc như vậy. Trong tập lệnh) (Tôi khá chắc chắn rằng không thể có tệp tmp, nhưng có thể sử dụng các tính năng vỏ thực sự tối nghĩa, có thể ...)
Volker Siegel

1
Có thể dễ dàng hơn để làm trực tiếp trong vim, nếu bạn sử dụng điều đó; Lựa chọn khối hình ảnh hình chữ nhật sẽ hữu ích, ví dụ: Có lời khuyên tốt về các câu hỏi vim tại vi.stackexchange.com , tất nhiên!
Volker Siegel

2

xóa số: cut -d" " -f2- < list.txt > temp.txt

chèn dòng vào temp.txt

làm số cat -n temp.txt| sed -e 's/^[ ]*\([0-9]*\)[ \t]*\(.*\)/\1. \2/' > list.txt


@don_crissti tại sao?
Ipor Sircer
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.