Thay thế một chuỗi trong một tập tin được đặt trước bởi một chuỗi khác


3

Tôi có một loạt các tập tin cấu hình như sau:

reader_0 = newcamd({
name = "Oct 1",
host = "hostname 1",
port = 27020,
user = "UNAME",
pass = "password1",
key  = "0102030405060708091011121314",
})

reader_1 = newcamd({
name = "Oct 2",
host = "hostname 2",
port = 27020,
user = "UNAME",
pass = "password2",
key  = "0102030405060708091011121314",
})

Làm cách nào có thể thay thế số cổng 27020 bằng một cổng khác, ví dụ: 22443, trong phần 'reader_1' bằng cách sử dụng sed ?

Cảm ơn bạn.


2
Tôi nghĩ rằng có một lỗi định dạng trong bài viết của bạn: Bạn đã không đặt bốn khoảng trắng trước khi kết thúc dấu ngoặc nhọn }). Điều này đặt ra câu hỏi: Hai phần từ các tệp khác nhau hay chúng thuộc về một tệp?
Stefan Hamcke

1
Bạn có người đọc_3 không?
Prvt_Yadav

1
Cái gì cố định và biến gì? Có phải "reader_1 = newcamd ({" đã cố định không? Cổng hiện tại luôn là 27020 hay có thể thay đổi không?
Jeff Schaller

Phần reader_1 sẽ luôn có định nghĩa "cổng" chứ?
Jeff Schaller

@JeffSchaller Có, tất cả các phần reader_ * đều có tham số 'port'. Số cổng hiện có là 27020 trong tất cả các tệp. Tất cả các biến là thực sự không đổi và giống nhau trong tất cả các tập tin.
Viktor Zaionchkovskyi

Câu trả lời:


2

Nếu bạn có nhiều dòng tương tự trong cùng một tệp, bạn sẽ phải nhập:

sed -i ':a;N;$!ba; s/27020/22443/2' file

Trong đó / 2 có nghĩa là nó sẽ thay thế trận đấu thứ hai cho 27020 . Bạn có thể kiểm tra lệnh bằng lệnh sed mà không có tham số -i để xem kết quả nào mang lại cho bạn.

Nếu không, với một đơn giản, sed -i 's/27020/22443/g' filenó sẽ hợp lệ, miễn là bạn biết tập tin nào sửa đổi.


1
Cảm ơn bạn. Đây là những gì tôi đã tìm kiếm!
Viktor Zaionchkovskyi

Tôi đã sử dụng lệnh này cho nhiều tệp sed -i - ': a; N; $! Ba; s /
27020/2443/2

6

Sử dụng tiền thân của sed ed:

ed -s input <<< $'/^reader_1 =\n/^port =\nc\nport = 22443,\n.\nw\nq'

Điều này sẽ gửi edmột chuỗi lệnh ANSI được trích dẫn ở đây - chuỗi lệnh để chỉnh sửa tệp. Các lệnh là, theo trình tự:

  1. /^reader_1 = - tìm kiếm dòng bắt đầu bằng "reader_1 ="
  2. /^port = - tìm kiếm chuyển tiếp từ đó cho dòng bắt đầu bằng "port ="
  3. c - thay đổi dòng đó
  4. port = 22443, - đến văn bản đó
  5. . - kết thúc văn bản thay thế
  6. w - ghi tập tin vào đĩa
  7. q - bỏ ed

Bạn có thể thắt chặt hoặc nới lỏng các biểu thức thông thường để khớp cẩn thận hơn hoặc ít hơn, theo dữ liệu thực tế của bạn.


3

Tôi giả sử rằng reader_0host = hostanme 1, reader_1host = hostname 2và như vậy.

Bạn có thể sử dụng lệnh này để thay thế từ file:

sed -i '/host = "hostname 2",/{N;s/port = 27020,/port = 22443,/}' file

2
Điều này cũng giả định rằng portluôn luôn theo sau host. Nếu chúng tôi giả định rằng các trường và đơn đặt hàng của chúng luôn giống nhau, thì bạn cũng có thể thêm 2 Ns và khớp từ /^reader_1\b/thay vì /host = "hostname 2",/.
JoL

Vâng, đó sẽ là tổng quát hơn.
Prvt_Yadav

1

Điều này có thể được thực hiện tốt hơn awktrong đó bạn có thể sử dụng kỹ thuật kiểu máy trạng thái:

awk '/^reader_1 = newcamd\({/ { section_found = 1} /})/ { section_found = 0 } section_found && /port = 27020,$/ { sub(/27020,$/, "22443,") } { print }' file1 > file2 && mv file2 file1

Giải trình:

Đặt cờ khi phần bắt đầu được tìm thấy:

/^reader_1 = newcamd\({/ {
    section_found = 1
}

Xóa cờ khi kết thúc phần được tìm thấy:

/})/ {
    section_found = 0
}

Thay thế số cổng mới khi ở phần bên phải và trên dòng bên phải:

section_found && /port = 27020,$/ {
    sub(/27020,$/, "22443,")
}

In tất cả các dòng:

{
    print
}

Gửi đầu ra cho tệp2 (một tệp tạm thời):

> file2

Nếu mọi thứ đã thành công, đổi tên file2 thành file1:

&& mv file2 file1

Bạn có thể làm cho các biểu thức thông thường là lỏng lẻo hoặc chặt chẽ khi bạn cần.

Loại mã này dễ đọc và bảo trì hơn sedhoặc edmã, đặc biệt nếu bạn định dạng mã tương tự như cách tôi giải thích.

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.