Đây là cách mạnh mẽ thực hiện kết hợp không tham lam của các chuỗi nhiều ký tự bằng cách sử dụng sed. Cho phép nói rằng bạn muốn thay đổi tất cả foo...bar
để <foo...bar>
ví dụ như vậy đầu vào này:
$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV
nên trở thành đầu ra này:
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
Để làm điều đó, bạn chuyển đổi foo và bar thành các ký tự riêng lẻ và sau đó sử dụng phủ định các ký tự đó giữa chúng:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV
Ở trên:
s/@/@A/g; s/{/@B/g; s/}/@C/g
đang chuyển đổi {
và }
thành chuỗi giữ chỗ không thể tồn tại trong đầu vào để những ký tự đó có sẵn để chuyển đổi foo
và bar
sang.
s/foo/{/g; s/bar/}/g
được chuyển đổi foo
và bar
đến {
và }
lần lượt
s/{[^{}]*}/<&>/g
đang thực hiện op mà chúng ta muốn - chuyển đổi foo...bar
thành<foo...bar>
s/}/bar/g; s/{/foo/g
đang chuyển đổi {
và }
trở lại foo
và bar
.
s/@C/}/g; s/@B/{/g; s/@A/@/g
đang chuyển đổi các chuỗi giữ chỗ trở lại các ký tự gốc của chúng.
Lưu ý rằng ở trên không phụ thuộc vào bất kỳ chuỗi cụ thể nào không có trong đầu vào vì nó tạo ra các chuỗi đó trong bước đầu tiên, cũng không quan tâm đến sự xuất hiện của bất kỳ biểu thức chính quy nào bạn muốn khớp vì bạn có thể sử dụng {[^{}]*}
nhiều lần nếu cần trong biểu thức để cô lập kết quả khớp thực tế mà bạn muốn và / hoặc với toán tử khớp số seds, ví dụ: chỉ thay thế lần xuất hiện thứ 2:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV