Làm thế nào để thêm số dòng cố định vào một tập tin?


21

Tôi có một tệp văn bản như thế này (sử dụng gVim trên Windows)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

Tôi muốn thêm một số vào mỗi dòng trong tệp. Không sử dụng :set number, nhưng để thêm số dưới dạng văn bản trước mỗi dòng, như sau, vì vậy số này là một phần của tệp.

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkcó lẽ là công cụ cho công việc này. Nhưng tôi đang ở trên Windows (thở dài).
roblogic

Đã trả lời ở đây rồi , đừng
bận

1
Có lẽ .. Hay đây là tổng quát hơn?
muru 14/2/2015

Nó tương tự, nhưng tôi không biết số dòng cố định là gì. Thứ hai, câu hỏi khác là về tất cả các dòng (và câu trả lời là như vậy) cho gVim trên Windows một cách cụ thể và đây là danh sách được đánh số đơn giản cho một đoạn chỉ trong vim đơn giản.
kenorb

3
Chà, tôi đoán rằng bài đăng sử dụng ot "vĩnh viễn" chỉ ra rằng bộ đệm sẽ được sửa đổi và các con số không phải là một thứ hoàn toàn trực quan (giống như bạn). Lý do chỉ định gvim trên Windows là để tránh các tiện ích bên ngoài như cathoặc nl, có thể thực hiện các dòng số, nhưng thường không có sẵn trên Windows (như OP chỉ ra từ nhận xét của họ về awk). Hai giải pháp hàng đầu là Vim thuần túy. Cuối cùng, tất cả các dòng so với một para chỉ là vấn đề lựa chọn phạm vi. Rõ ràng không phải là một vấn đề lớn.
muru 14/2/2015

Câu trả lời:


36

Trong thời trang Vim thuần túy:

:%s/^/\=line('.').". "

Giải trình:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

Xem :help \=:help line().

Sử dụng một biểu thức trong phần thay thế là rất mạnh mẽ và FWIW là một điểm khá tốt để nhập vimscript.


Làm cách nào để thêm lệnh rất hữu ích này vào sơ đồ bàn phím trong vimrc?
vũ trụ

Để đến chủ đề trợ giúp của vim để thay thế::help sub-replace-expression
akurtser

9

Một điều thú vị về macro Vim là chúng có thể lặp lại (chúng có thể tự gọi):

  1. Xóa sổ đăng ký q: qqq
  2. Thêm số vào dòng đầu tiên: ggI1.(đừng quên khoảng trắng!)
  3. Di chuyển trở lại để bắt đầu dòng và bắt đầu ghi một macro: 0qq
  4. Sao chép số: yW
  5. Di chuyển xuống một dòng và dán số: +P
  6. Di chuyển trở lại đầu dòng và tăng số: 0<c-a>
  7. Di chuyển trở lại điểm bắt đầu của dòng (để macro không bị vỡ khi tăng gấp đôi số liệu!): 0
  8. Gọi macro một lần, để làm cho nó đệ quy. Tại thời điểm này, vẫn không có gì trong đăng ký q, vì vậy sẽ không có gì xảy ra : @q.
  9. Lưu macro: q
  10. Gọi macro một lần nữa và xem tia lửa bay!: @@

Macro sau đó sẽ tiếp tục gọi chính nó cho đến khi đến cuối tập tin.

Bạn có thể sử dụng thủ thuật macro đệ quy cho nhiều vấn đề tương tự khác, vì vậy đây là một mẹo hay để nhận biết.

Nếu bạn không muốn sử dụng macro đệ quy vì một số lý do, bạn có thể bỏ qua bước 1 và 8 và sử dụng số đếm để chạy macro nhiều lần, ví dụ: 100@qsẽ chạy macro q100 lần.


1
Công cụ mạnh mẽ, tôi cúi đầu làm chủ của bạn. Macro giống như ma thuật đen đối với tôi ...
roblogic

1
@ropata, macro chỉ là một chuỗi các lệnh chế độ thông thường (chủ yếu).
romainl

1
@romainl Tôi nghĩ tốt hơn nên nghĩ về nó như một chuỗi các lần nhấn phím .
Giàu

2
@Rich, nó có thể là một chuỗi nhiều thứ, bao gồm các lệnh ex.
romainl

2
@romainl Vâng, đó là lý do tại sao tôi nghĩ tốt nhất nên nghĩ về nó như tổ hợp phím. Nó phát lại chính xác những gì bạn gõ trên bàn phím (bao gồm, như bạn nói, các lệnh ex), như thể bạn đã gõ tất cả bằng tay.
Giàu

7

Tôi thích sử dụng lệnh vim toàn cầu để hoàn thành các nhiệm vụ như thế này. Điều này áp dụng để thêm lần lặp vào đầu dòng hoặc sửa đổi một ký hiệu trong văn bản. Nó trông phức tạp hơn các giải pháp khác, nhưng là một mô hình khá linh hoạt để sử dụng khi bạn có nó tiện dụng, và dễ dàng sửa đổi mà không cần suy nghĩ nhiều.

Đầu tiên, chọn phạm vi của bạn (dòng nào bạn muốn áp dụng này). Tôi thường sử dụng các dấu (ví dụ matrên dòng đầu tiên và mbtrên dòng thứ hai, nhưng bạn cũng có thể sử dụng số dòng hoặc lựa chọn trực quan), sau đó nhập một sửa đổi của lệnh sau (hiện được điều chỉnh cho trường hợp sử dụng của bạn)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

Giải cấu trúc

:let i=1

Điều này thiết lập biến ivới một giá trị bắt đầu. Thông thường danh sách bắt đầu bằng 1, vì vậy tôi đặt i thành 1.

|

Thanh bắt đầu một lệnh mới

'a,'b

Điều này đặt phạm vi của lệnh tiếp theo. Tôi đang đi từ đánh dấu ađến đánh dấu b, sẽ được đặt trên dòng đầu tiên và dòng cuối cùng trong danh sách của bạn.

g/^/

Đây là lệnh toàn cầu. Nó tìm kiếm tệp (hoặc phạm vi) cho một biểu thức chính quy định và sẽ thực thi phần còn lại của dòng lệnh trên mỗi dòng khớp. Tôi phù hợp với mọi dòng bằng cách tìm kiếm "đầu dòng". Nếu bạn có văn bản như

Item some txt
other text

Item second item
whatever
Item third

và chỉ muốn đặt các nhãn này ở phía trước Itemvà bỏ qua các dòng khác, thực hiện g/Item/hoặc g/^Item/thay vào đó (giả sử văn bản Mục bằng chữ)

s/^/\=i.". "/

Điều này thực hiện biểu thức chính quy để thay thế phần đầu của dòng bằng giá trị được inối với a .. Nói chung, bạn có thể làm điều này với bất cứ điều gì ( Itemví dụ thay thế nhãn bằng số).

|let i=i+1

Mặc dù thanh bắt đầu một lệnh mới, nó sẽ thiết lập một lệnh thứ hai để chạy trong lệnh toàn cầu, thay vì sau khi toàn cầu hoàn tất. Kết quả là chúng tôi tăng itrước khi dòng tiếp theo được xử lý bởi g. Đây là một nơi linh hoạt khác. Việc sửa đổi i có thể là bất cứ điều gì (tăng thêm 2, gọi một hàm tạo ra phần tử tiếp theo của chuỗi Fibonacci, bất cứ điều gì).


7

Thêm số vào tất cả các dòng

Có thể sử dụng :%!nl -bahoặc :%!cat -ncác lệnh sẽ thêm số dòng cho tất cả các dòng.

Trên Windows, bạn đã cài đặt Cygwin / MSYS / SUA.

Thêm số vào các dòng được chọn

Để chỉ thêm số cho các dòng đã chọn, vui lòng chọn chúng trong chế độ trực quan ( vvà con trỏ), sau đó khi hoàn tất - thực hiện lệnh: :%!nl(bỏ qua các dòng trống) hoặc :%!cat -n(bao gồm các dòng trống).

Định dạng

Để xóa khoảng trắng thừa, chọn chúng trong khối trực quan ( Ctrl+ v) và xóa chúng ( x).

Để thêm một số ký tự ( ., :, )) sau khi các con số, chọn chúng trong khối thị giác ( Ctrl+ v), sau đó nối các ký tự ( A, gõ ký tự, sau đó kết thúc với Esc).


2
Điều này không đưa ra định dạng giống như được đưa ra trong câu hỏi. Tuy nhiên, tôi thích sự đơn giản của giải pháp.
Karl Yngve Lervåg

@ KarlYngveLervåg Cảm ơn, bao gồm điều đó trong câu trả lời.
kenorb

5

Một sửa đổi của câu trả lời của romainl :

:%s/^\(\d\+\. \)\?/\=line('.').". "

Điều này sẽ không chỉ thêm số dòng, nó cũng sẽ thay thế số dòng đang tồn tại. Của, nếu bạn đã chèn một dòng giữa chừng, nó sẽ đánh số lại mọi thứ như mong đợi.

Điều này hoạt động bằng cách thay thế bất kỳ số theo sau a. và một khoảng trắng ở đầu dòng với một số mới. Điều này rõ ràng sẽ bị phá vỡ nếu bạn có một dòng đã bắt đầu với mẫu này, vì vậy hãy sử dụng với suy nghĩ.

Phần được thêm vào:

  • ^ - Bắt đầu dòng
  • \( - Bắt đầu phân nhóm mới
  • \d\+ - Ghép một chữ số một lần trở lên
  • \. - Ghép một dấu chấm ( .) và dấu cách .
  • \) - Kết thúc phân nhóm
  • \? - Làm cho nhóm tùy chọn, để nó hoạt động như trước nếu chưa có số nào trên dòng này.

Gợi ý tiền thưởng:
Để xóa số dòng, bạn có thể sử dụng cùng một mẫu với phần trả lại trống:

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

Số này có hai dòng đầu tiên và bạn có thể nhấn @qđể đánh số các dòng tiếp theo (hoặc nhập ex. 18@qNếu bạn muốn đánh số tổng số 20 dòng).

Giải trình:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

Lợi ích của việc này là nó không yêu cầu bất kỳ lệnh bên ngoài nào, rất hữu ích nếu bạn làm việc với Vim trên Windows chẳng hạn.


Sau khi gõ 1. <esc>hbạn đang ở cột thứ hai, không phải cột đầu tiên. Tôi sẽ thay thế hbằng 0, sau đó tôi nghĩ giải pháp của bạn sẽ rất tốt.
Karl Yngve Lervåg

@ KarlYngveLervåg Rất tiếc, đó là một lỗi đánh máy. Cảm ơn, đã sửa nó.
Doorknob

Không vấn đề gì. Tuy nhiên, bạn vẫn chưa cập nhật lời giải thích. Ngoài ra: Trên nhiều bàn phím, ^chờ ký tự thứ hai để cho phép nhập tổ hợp như thế nào ^a -> â. Tôi vẫn đồng ý giải pháp tốt nhất của nó, nhưng tôi nghĩ điều này cũng nên được đề cập.
Karl Yngve Lervåg

3

Tôi nghĩ rằng câu trả lời được chọn là tốt nhất, nhưng trong phạm vi đa dạng, tôi sẽ đưa ra một giải pháp thay thế bằng cách sử dụng một chương trình bên ngoài:

:%!cat -n

Điều này sẽ lọc toàn bộ bộ đệm của bạn (như được biểu thị bởi %) thông qua chương trình bên ngoài cat, trong đó -ncờ sẽ bổ sung cho mỗi dòng đầu vào với một số dòng.

Tất nhiên, điều này đòi hỏi bạn phải catcài đặt, điều này đúng với (có thể) tất cả các hệ thống giống Unix.

Kiểm tra :help :range!để biết thêm chi tiết về lọc qua các chương trình bên ngoài.


1
Tôi nhận ra rằng người hỏi đang sử dụng gVim trên Windows, vì vậy giải pháp này có thể sẽ không hoạt động ở đó. Tuy nhiên, tôi nghĩ nó vẫn cung cấp một số cơ hội cho những người khác học hỏi từ nó.
tommcdo

Nếu bạn đã cài đặt msysgitvà thêm nó vào PATH của mình (IIRC thì đó là tùy chọn cài đặt), giải pháp này cũng sẽ hoạt động trên Windows.
Martin Tournoij

4
cat -nkhông phải là POSIX, nhưng nllà, vì vậy nó có thể là một lựa chọn tốt hơn.
muru

2

Một giải pháp hackish bit có thể là như sau (mọi thứ được viết giữa <và> sẽ được chèn sau khi nhấn Ctrl+ v):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

Giải cấu trúc

:%normal {commands}

chạy lệnh chế độ bình thường trên mỗi dòng được chỉ định bởi phạm vi, trong trường hợp này là mỗi dòng

:redir @"

chuyển hướng mọi đầu ra được thực hiện bởi các lệnh ex đến bộ đệm không tên.

:.=

là một lệnh ex xuất ra số dòng hiện tại (không may có dòng mới trước đó)

:redir END

dừng chuyển hướng đến bộ đệm không tên

I<C-R>".<Tab><Esc>

chèn nội dung của bộ đệm không tên với a. và một tab ở phía trước của mỗi dòng và thoát khỏi chế độ chèn.

kdd

đi lên một dòng và loại bỏ dòng mới là kết quả của lệnh :. =.

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.