Bất kỳ trình soạn thảo văn bản có thể áp dụng một số toán học để thay thế văn bản?


15

Tôi có tệp XML lớn

<obj param="2542">
<obj param="2333">
<obj param="6433">

Tôi cần tăng tất cả các giá trị "param" lên một số. Tôi có thể khớp các số mà tôi cần với tìm kiếm regrec trong nhiều trình soạn thảo, nhưng làm thế nào để áp dụng một số phép toán để thay thế?


1
Hệ điều hành nào? Thay vào đó, bạn có hài lòng với một kịch bản shell hay không (điều này khá dễ)? Dù sao, tôi chắc chắn vimemacscó thể làm điều này, nhưng nó có thể yêu cầu viết một kịch bản thay vì sử dụng một lệnh duy nhất.
frabjous

@frabjous dưới cửa sổ. Tôi thà không viết bất cứ điều gì nếu có thể. Nhưng nếu bạn đăng một shell script tôi chắc chắn nó sẽ hữu ích với nhiều người.
serg

Câu trả lời:


18

Sau khi chọc thêm một chút, hóa ra vim có thể làm điều đó với một lệnh duy nhất, mà không cần kịch bản. Ví dụ: để thêm 50 vào tất cả các số sau <obj param="bạn có thể sử dụng:

:%s@<obj param="\(\d\+\)@\='<obj param="' . (submatch(1) + 50)@g

Hãy để tôi phá vỡ nó.

: là cách chung để nhập / biểu thị chế độ dòng lệnh trong vim.

%có nghĩa là trong phạm vi của toàn bộ tài liệu; thay vào đó, bạn có thể đặt trong một phạm vi số, ví dụ, 1,50chỉ thực hiện trong 50 dòng đầu tiên.

s là viết tắt để thay thế (bạn có thể viết toàn bộ từ nếu bạn thích)

@là dấu phân cách; bạn có thể sử dụng bất kỳ ký tự nào khác miễn là nó không nằm trong những gì bạn đang tìm kiếm. Chỉ cần sử dụng ba lần. (Cú pháp tương tự sed.)

Tất cả mọi thứ cho đến lần xuất hiện tiếp theo của dấu phân cách @ là mẫu reg ex để tìm kiếm, trong trường hợp này <obj param="tiếp theo \d\+là số chữ số bất kỳ. Các \(\)đang có để thiết lập toàn bộ chuỗi này các chữ số là một nhóm đơn reg cũ mà sẽ phù hợp với backreferences như \1, hoặc vim của submatchlệnh.

Sau đó, dấu phân cách @đánh dấu những gì tiếp theo là văn bản thay thế.

\=đầu ở đây có nghĩa là để thay thế kết quả của một số biểu thức được đánh giá, thay vì một mẫu hoặc chuỗi reg ex, là chìa khóa ở đây.

Sau đó, chúng tôi đã '<obj param="'bắt đầu các văn bản thay thế. Tiếp .theo là chức năng của vim để nối chuỗi.

submatch(1)là một hàm dựng sẵn vim chỉ có thể được sử dụng trong lệnh thay thế và trả về chuỗi giống như biểu thức chính quy \1; bạn sẽ sử dụng submatch(2)tương đương với regex \2, v.v. ( \0Là mô hình phù hợp với tổng thể, nhưng chúng tôi không muốn điều đó ở đây.) Các \(\)trong mô hình tìm kiếm được sử dụng để đánh dấu tắt những gì đếm như submatch(1).

Do đó (submatch(1) + 50)đưa ra kết quả của việc thêm 50 vào số mà các chữ số theo sau <obj param="trong mẫu mẫu tìm kiếm.

Dấu phân cách @một lần nữa được sử dụng để đánh dấu phần cuối của văn bản thay thế.

Cờ gđược sử dụng để làm cho sự thay thế toàn cầu; bạn có thể bỏ qua phần này nếu bạn chỉ muốn thay thế phiên bản đầu tiên trên mỗi dòng.

Bạn có thể tìm ra cách thêm các số khác nhau, hoặc trừ hoặc chia, v.v.


Điều này thật tuyệt, tôi đã có một tệp GPX bị hỏng vì các giá trị kinh độ hoàn toàn không hợp lệ. May mắn thay, vĩ độ là ổn vì vậy bằng cách sử dụng bản đồ, tôi có thể tìm ra giá trị đúng đầu tiên là gì, làm một số phép toán và tìm ra rằng tôi cần phải trừ 4294.567548 từ mỗi giá trị để làm cho đúng. Điều vấp ngã duy nhất tôi có là phương pháp này không hoạt động trên số dấu phẩy động, vì vậy tôi chỉ thực hiện mỗi bên của dấu thập phân là các thay thế riêng biệt, một -4294 và một -567548.
nhồi vào

7

Trong Emacs (kể từ phiên bản 23): sử dụng \, để thực thi mã Lisp tùy ý trong thay thế regrec . Ví dụ: để bình phương số bạn có thể sử dụng

M-x replace-regexp
param="\([0-9]+\)"
param="\,(* \#1 \#1)"

Trong Vim: bắt đầu văn bản thay thế của bạn với \=(xem :help sub-replace-special). Ví dụ: để bình phương các số:

s!param="\([0-9]\+\)"!\='param="'.submatch(1)*submatch(1).'"'!

Một số trình soạn thảo cho phép bạn thực hiện loại điều này với macro: xác định macro mà 1. tìm kiếm kết quả khớp tiếp theo và 2. thực hiện thay thế (sử dụng công cụ bên ngoài để tính toán số học nếu cần thiết); lặp lại macro nhiều lần như bạn có.


Câu trả lời không nản lòng. Ngắn và bạn bao gồm 2 biên tập viên + trường hợp chung.
derekv

1

Bạn có thể sử dụng vim để làm điều đó cho bạn. Chỉ cần mở tệp của bạn và ghi lại một macro . Ví dụ: Tìm kiếm bất kỳ số nào

/[0-9]{1,}

sau đó nhấn q và a (lưu trữ macro trong thanh ghi a). Sau đó, nhấn Ctrl-X (tăng số 1) và nhấn n (để biết kết quả tìm kiếm tiếp theo) sau đó. Sau khi bạn đã làm điều đó, nhấn q lần nữa để lưu macro. Bây giờ bạn có thể áp dụng macro cho số tiếp theo bằng cách nhấn @ + a. Điều này sẽ thay đổi số hiện tại và nhảy sang số tiếp theo. Bằng cách lặp lại hoặc sử dụng x @ a, bạn có thể lặp lại x lần đó.

Chà, mô tả đó có thể không đủ để chỉ ra cách nó có thể được thực hiện. Chỉ cần tham khảo một hướng dẫn mô tả cơ chế vĩ mô trong vim.


Nếu tôi cần thay đổi số không phải bằng 1 mà bằng một triệu thì sao? Hoặc có thể sử dụng một số phép nhân / chia?
serg

1
Thật dễ dàng nếu bạn muốn thêm hằng số x vào mỗi số: x + Ctrl + a. Bạn có cần thêm số khác nhau?
evnu
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.