Tương tự như câu trả lời tại https://vi.stackexchange.com/a/818/227 , bạn có thể sử dụng lệnh toàn cầu.
Với nó, bạn có thể hướng dẫn vim tìm kiếm các dòng khớp với một mẫu và sau đó thực hiện các lệnh trên nó.
Trong trường hợp của bạn, bạn muốn thêm văn bản vào các dòng bắt đầu bằng "Cấp N:", vì vậy lệnh toàn cầu của chúng tôi có thể là
:g/^Level \d:/{COMMANDS}
Sử dụng lệnh thay thế (thay thế biểu thức chính quy) cho lệnh
Các lệnh vui hơn. Tôi thường thích thay thế biểu thức chính quy cho những thứ như thế này, vì nó dễ sử dụng các biến.
Ví dụ cho câu hỏi của bạn
:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1
Làm thế nào nó hoạt động
Trong phần thay thế của lệnh thay thế có thể là một biểu thức.
Điều đầu tiên chúng ta sẽ làm là đặt một biến i
là số bắt đầu. Tôi đã chọn 1, nhưng bất kỳ số nào sẽ làm.let i = 1
Sau đó, chúng tôi chạy lệnh toàn cầu của chúng tôi, điều này cho phép chúng tôi thực hiện một hành động trên các dòng khớp. g/^Level \d:/
Chúng ta sẽ có lệnh toàn cầu của chúng ta chèn giá trị và tăng bộ đếm của chúng ta bằng cách sử dụng lệnh thay thế và lệnh let. s/^/\=printf("%02d ", i)/ | let i = i+1
Biểu thức chính quy của lệnh thay thế tìm thấy phần đầu của dòng ^
và thay thế nó bằng một biểu thức và biểu thức của chúng ta sẽ là kết quả của một bản in được định dạng. Giống như trong ngôn ngữ C, printf của vim lấy các tham số định dạng. %02d
có nghĩa là chuyển đổi một đối số như thể đó là một số thập phân d
, chiếm ít nhất 2 khoảng trắng 2
và dấu bằng 0 0
. Để biết chi tiết và các tùy chọn chuyển đổi khác (bao gồm định dạng dấu phẩy động), xem :help printf
. Chúng tôi cung cấp cho printf biến đếm của chúng tôi i
và nó cho chúng tôi 01
lần đầu tiên, 02
lần thứ hai, v.v ... Điều này được sử dụng bởi lệnh thay thế để thay thế đầu dòng, chèn hiệu quả kết quả của printf ở đầu.
Lưu ý rằng tôi đặt một khoảng trắng sau d : "%02d "
. Bạn đã không hỏi nó trong câu hỏi (và tôi không thấy đầu ra ví dụ), nhưng tôi nghi ngờ bạn muốn tách số này khỏi từ "Cấp độ". Xóa khoảng trắng khỏi chuỗi được cung cấp cho printf để có số được chèn ngay bên cạnh L in Level.
Cuối cùng, điều đó làm let i = i + 1
tăng bộ đếm của chúng tôi sau mỗi lần thay thế.
Điều này có thể được áp dụng chung để thay thế các phần của dòng được khớp với các tiêu chí khác bằng dữ liệu chức năng tùy ý.
Sử dụng các lệnh thông thường kết hợp
Điều này là tốt cho chèn đơn giản hoặc chỉnh sửa phức tạp. Giống như với thay thế, chúng tôi sẽ sử dụng toàn cục để khớp, nhưng thay vì thay thế biểu thức thông thường, chúng tôi sẽ thực hiện một loạt các hoạt động như thể được gõ bởi người dùng.
Ví dụ cho câu hỏi của bạn
:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1
Làm thế nào nó hoạt động
Các giá trị được sử dụng rất giống với thay thế (chúng tôi vẫn đang sử dụng printf để định dạng số của chúng tôi để làm cho nó 0 được đệm với 2 chữ số), nhưng hoạt động thì khác.
Ở đây chúng ta sử dụng lệnh exec, lấy một chuỗi và chạy chuỗi dưới dạng một lệnh ex ( :help :exe
). Chúng tôi xây dựng một chuỗi kết hợp "bình thường! I" với dữ liệu của chúng tôi, đó sẽ là "bình thường! I01" lần đầu tiên và "bình thường! I02" lần thứ hai, v.v.
Các normal
lệnh Thực hiện các hoạt động như thể trong chế độ bình thường. Trong ví dụ này, lệnh thông thường của chúng ta là I
, chèn vào đầu dòng. Nếu chúng ta đã sử dụng dd
nó sẽ xóa dòng, o
sẽ mở một dòng mới sau dòng phù hợp. Như thể bạn tự gõ I
(hoặc bất kỳ thao tác nào khác) ở chế độ bình thường. chúng tôi sử dụng !
sau normal
để đảm bảo không có ánh xạ nào cản đường chúng tôi. Xem :help :normal
.
Giá trị được chèn vào sau đó là giá trị của printf của chúng tôi, như trong ví dụ đầu tiên về việc sử dụng thay thế.
Phương pháp này có thể lạ hơn regex, bởi vì bạn có thể thực hiện những việc như execute "normal! ^2wy" . i . "th$p"
, sẽ đi đến phần đầu của văn bản ^
, di chuyển về phía trước 2 từ 2w
, kéo dài cho đến khi ký tự thứ ih y" . i . "th
, di chuyển đến cuối dòng $
và dán p
.
Điều này gần giống như chạy macro, nhưng thực tế không sử dụng hết thanh ghi và có thể kết hợp các chuỗi từ bất kỳ biểu thức nào. Tôi thấy điều này rất mạnh mẽ.
Cách tiếp cận nơi mỗi cấp có bộ đếm riêng
Bạn có thể muốn mỗi cấp độ có được bộ đếm riêng của mình. Nếu bạn biết số cấp tối đa trước thời hạn, bạn có thể thực hiện các thao tác sau (thêm mã bổ sung để tìm mức lớn nhất có thể không quá khó, nhưng sẽ khiến câu trả lời này quá dài. Điều này sẽ kéo dài).
Đầu tiên, hãy để tôi tự do, trong trường hợp chúng tôi đã sử dụng nó như một số nguyên. Chúng tôi không thể chuyển đổi tôi thành một danh sách, chúng tôi phải tạo ra nó theo cách đó.
:unlet! i
Tiếp theo, hãy đặt i thành một danh sách chứa số cấp. Bạn đã cho thấy 2 trong câu hỏi của bạn, nhưng hãy giả sử 10 cho niềm vui của nó. Vì lập chỉ mục danh sách là 0 dựa trên và tôi không muốn sửa lỗi cho 1 dựa trên danh sách của bạn, chúng tôi sẽ chỉ tạo đủ các yếu tố (11) và không bao giờ sử dụng chỉ mục 0.
:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile
Tiếp theo, chúng ta cần một cách để có được số cấp. May mắn thay, thay thế cũng có sẵn như là một chức năng, vì vậy chúng tôi sẽ cung cấp cho dòng của chúng tôi và trích xuất số cấpsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")
Vì tôi bây giờ là một danh sách gồm 11 1
giây (mỗi chỉ số là bộ đếm cho cấp độ của chúng tôi), bây giờ chúng tôi có thể điều chỉnh một trong các ví dụ trên để sử dụng kết quả của sự thay thế này:
Thông qua lệnh thay thế:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1
Thông qua lệnh thông thường:
:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1
Ví dụ đầu vào:
Level 1: stuff
Level 1: Stuff
Some text
Level 3: Other
Level 1: Meh
Level 2: More
Ví dụ đầu ra:
01 Level 1: stuff
02 Level 1: Stuff
Some text
01 Level 3: Other
03 Level 1: Meh
01 Level 2: More