Thay thế nội dung nhóm chụp regex bằng sed


16

Tôi đang cố gắng chỉnh sửa tệp nginx.conf của mình bằng lập trình, trong đó có một dòng như thế này:

        access_log /var/log/nginx/access.log;

mà tôi muốn trông như thế này:

        access_log /dev/stdout;

Tôi tin rằng regex ^\s*access_log([^;]*);sẽ chụp /var/log/nginx/access.logphần trong nhóm chụp, nhưng tôi không chắc làm thế nào để thay thế chính xác nhóm chụp bằng sed?

Tôi đã thử

echo "        access_log /var/log/nginx/access.log;" | sed 's/^\s*access_log([^;]*);/\1\\\/dev\\\/stdout/'

nhưng tôi đang nhận được lỗi:

sed: -e expression #1, char 45: invalid reference \1 on `s' command's RHS

Nếu tôi thử sed -rthì không có lỗi, nhưng đầu ra không như tôi mong đợi:

 /var/log/nginx/access.log\/dev\/stdout

Tôi đang cố gắng trở nên thông minh với nhóm chụp và không chú ý và không tìm kiếm trực tiếp "access_log /var/log/nginx/access.log;" trong trường hợp phân phối thay đổi vị trí tệp nhật ký mặc định.


1
sed '/access_log/s|/[^;]\+|/dev/stdout|'
Costas

@Costas Nếu bạn muốn đưa ra câu trả lời tôi sẽ nâng cao bạn vì điều đó cũng hiệu quả!
Abe Voelker

Câu trả lời:


16

Một vài sai lầm ở đó.

Đầu tiên, vì sedsử dụng các biểu thức chính quy cơ bản, bạn cần \(\)tạo một nhóm chụp. Công -rtắc cho phép các biểu thức chính quy mở rộng, đó là lý do tại sao bạn không gặp lỗi. Xem tại sao tôi cần thoát các ký tự regex trong sed để được hiểu là các ký tự regex? .

Thứ hai, bạn đang đặt nhóm chụp sai vị trí. Nếu tôi hiểu bạn chính xác, bạn có thể làm điều này:

sed -e 's!^\(\s*access_log\)[^;]*;!\1 /dev/stdout;!' your_file

Lưu ý việc sử dụng !như các dấu phân cách regex để tránh phải thoát các dấu gạch chéo về phía trước /dev/stdout.


Cảm ơn, làm việc tuyệt vời! Tôi chưa thể đánh dấu điều này là đã được chấp nhận, nhưng sẽ quay lại sau 9 phút để làm điều đó.
Abe Voelker

1
@AbeVoelker Bạn rất hoan nghênh. Tôi rất vui vì tôi có thể giúp.
Joseph R.

5

Trong regrec của bạn, bạn nên biết đó \No.tham chiếu trở lại cho mẫu trong ngoặc (). Vì vậy, regrec nên được's@^(\s*access_log ).*$@\1/dev/stdout/;@'

tôi có thể phục vụ

sed '/access_log/s|/[^;]\+|/dev/stdout|'

GỢI Ý: Cho dù bạn có ý định sử dụng /bên trong người cha, bạn có thể tự do thay đổi s///cho mọi biểu tượng bạn muốn chẳng s###hạn


Cảm ơn, tôi ước tôi có thể chấp nhận hai câu trả lời! Tôi không còn hối tiếc vì đã không đọc hết các trang của người đàn ông trước khi yêu cầu giúp đỡ sau khi xem các giải pháp.
Abe Voelker

3

Thay vì nắm bắt nó, tại sao không tìm thấy nó và thay thế? I E:

sed "/access_log/ s| /.*;| /dev/stdout;|"

Nó tìm kiếm các dòng khớp với " access_log" sau đó trên bất kỳ dòng nào sẽ thay thế " /whatever/path/is/there;" bằng " /dev/stdout;"

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.