Làm thế nào để thay thế nội dung giữa hai mẫu từ tệp?


9

Tôi có định dạng sau của tệp:

<common>
fitnes=0
genetic=1
method=0
</common>
<inputs>
foo=bar
bar=foo
</inputs>
<limits>
balance=200.00
</limits>

và tôi muốn xóa mọi thứ ở giữa <inputs></inputs>(không bao gồm mẫu tự) và thay thế nó bằng nội dung từ một tệp khác (ví dụ foo.txt). Nói cách khác, dòng có foo=barbar=foosẽ được thay thế bằng một nội dung khác.

Có thể nó giống với cách bạn xóa một trận đấu nhiều dòng , như:

:g/<inputs/,/inputs>/d

nhưng tôi không chắc chắn với những gì tôi nên thay thế dđể chèn nội dung của tệp khác, nhưng tôi muốn giữ mẫu phù hợp.

Cách tiếp cận tương tự sẽ là loại bỏ nội dung bên trong của thẻ html , như

:/<inputs>/norm vitd

nhưng sau đó tôi không biết làm thế nào bạn sẽ thêm vào nó nội dung từ tệp.

Lý tưởng nhất là tôi đang cố gắng tìm một lớp lót, vì nó sẽ là một phần của một kịch bản khác.

Làm thế nào tôi có thể đạt được điều đó?

Câu trả lời:


10

Một sự thay thế có thể được sử dụng để thay thế một mẫu với kết quả của một biểu thức như thế này:

:keeppatterns %s;<inputs>\zs\_.\{-}\ze</inputs>;\=insert(readfile('test.txt'), '')

Xem :help sub-replace-expression

Lưu ý rằng keeppatternsngăn substitutelệnh thêm bất cứ điều gì vào lịch sử tìm kiếm và duy trì "đăng ký mẫu tìm kiếm cuối cùng" - xem :help "/. Đó là thực hành tốt để ngăn chặn kịch bản từ không cần thiết sửa đổi trạng thái toàn cầu Vim với các bổ lệnh keepalt, keepjumps, lockmarks, keepmarks, và keeppatterns.


5

Một cách tiếp cận khác từ Gary là:

:g/^<inputs>/+,/^<\/inputs>/-d|-r dummy

Đầu tiên xóa mọi thứ trong mẫu đã cho, hơn là sử dụng :rlệnh để đọc dữ liệu từ tệp giả. Bây giờ nếu bạn cần trích xuất tên tệp từ các dòng giữa <input>/</input>mẫu, nó sẽ phức tạp hơn một chút.


4

Điều này dường như hoạt động, ít nhất là trên một hệ thống Unix:

:/<inputs>/+1,/<\/inputs>/-1!cat foo.txt

Nó sử dụng {range}!{filter}lệnh để lọc các dòng từ một <inputs>đến một trước </inputs>thông qua chương trình bên ngoài cat foo.txt. Trong trường hợp này, catbỏ qua đầu vào tiêu chuẩn của nó, vì vậy các dòng gốc sẽ bị xóa và thay thế bằng nội dung của tệp foo.txt.

Xem:

:help :range!
:help cmdline-ranges

2

Tôi cảm thấy một vĩ mô sẽ là một cách tiếp cận dễ dàng hơn. Đặc biệt, nếu bạn có nhiều nơi khác nhau để làm như vậy.

  1. Chỉ giữ 2 tệp đó mở.
  2. Bây giờ trong tập tin đầu tiên bắt đầu ghi bởi qa,( alà tên bản ghi).
  3. Tìm kiếm mẫu bắt đầu, nhấn xuống , sau đó nhấn Ctrl- v, tìm kiếm mẫu kết thúc, nhấn lên . Bây giờ phần bạn muốn xóa được chọn. Xóa đi.
  4. Đánh dấu vị trí bằng cách sử dụng ma( alà tên đánh dấu) và lưu tệp.
  5. Chuyển đến tệp thứ 2, bằng :b2lệnh và tương tự chọn phần theo tiêu chí bắt đầu / kết thúc của bạn.
  6. Quay trở lại tập tin này nhấn ađể đi đến điểm đó. Dán ở đó bởi p.
  7. Tìm kiếm tiêu chí kết thúc một lần nữa và vượt qua phần để không nhấn lại.
  8. Thoát khỏi mã hóa bằng cách nhấn q.
  9. Lặp lại số lần bằng 40@a.

1
Cảm ơn đề xuất này, nó ổn, nhưng nó sẽ không giúp ích gì trong trường hợp cụ thể này, vì tôi đang tìm giải pháp không tương tác như một phần của extập lệnh nơi tôi có thể chỉ định tệp nào sẽ chèn tùy thuộc vào đối số đầu vào của người dùng.
kenorb

1

Nếu đây là một nỗ lực khác để phân tích XML bằng các Công cụ không phải XML, thì không.

Các giải pháp ở đây là hợp lệ, nhưng ý định có thể không. Nếu XML không phải từ một nguồn được thuần hóa tốt, bạn có thể có các lối thoát, CDATA hoặc khoảng trắng trong thẻ!

Vì vậy, xsltproc từ lệnh trong vi có thể đối phó với điều đó.


Tệp này không thực sự đúng định dạng XML, nhưng thực tế nó không phải là initệp được ghi chép tốt có 3 thẻ giống như XML đó.
kenorb
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.