Để thoát các biến được sử dụng ở phía bên trái và bên phải của slệnh trong sed(ở đây $lhsvà $rhstương ứng), bạn sẽ làm:
escaped_lhs=$(printf '%s\n' "$lhs" | sed 's:[][\/.^$*]:\\&:g')
escaped_rhs=$(printf '%s\n' "$rhs" | sed 's:[\/&]:\\&:g;$!s/$/\\/')
sed "s/$escaped_lhs/$escaped_rhs/"
Lưu ý rằng $lhskhông thể chứa một ký tự dòng mới.
Đó là, trên LHS, thoát tất cả các toán tử regrec ( ][.^$*), ký tự thoát ( \) và dấu phân cách ( /).
Trên RHS, bạn chỉ cần thoát &, dấu phân cách, dấu gạch chéo ngược và ký tự dòng mới (mà bạn thực hiện bằng cách chèn dấu gạch chéo ngược ở cuối mỗi dòng trừ dấu cuối ( $!s/$/\\/)).
Giả sử bạn sử dụng /làm dấu phân cách trong các sed slệnh của mình và rằng bạn không kích hoạt REs mở rộng với -r(GNU sed/ ssed/ ast/ busybox sed) hoặc -E(BSD, astGNU gần đây, busybox gần đây) hoặc PCRE với -R( ssed) hoặc RE Augmented với -A/ -X( ast) tất cả đều có thêm toán tử RE.
Một vài quy tắc cơ bản khi xử lý dữ liệu tùy ý:
- Đừng dùng
echo
- trích dẫn các biến của bạn
- xem xét tác động của miền địa phương (đặc biệt là bộ ký tự của nó: điều quan trọng là các lệnh thoát
sed được chạy trong cùng một miền với sedlệnh sử dụng các chuỗi thoát ( sedví dụ với cùng một lệnh)
- đừng quên ký tự dòng mới (ở đây bạn có thể muốn kiểm tra xem
$lhscó chứa bất kỳ và thực hiện hành động nào không).
Một tùy chọn khác là sử dụng perlthay vì sedvà truyền các chuỗi trong môi trường và sử dụng các toán tử \Q/ \E perlregrec để lấy chuỗi theo nghĩa đen:
A="$lhs" B="$rhs" perl -pe 's/\Q$ENV{A}\E/$ENV{B}/g'
perl(theo mặc định) sẽ không bị ảnh hưởng bởi bộ ký tự của miền địa phương, như ở trên, nó chỉ coi các chuỗi là mảng byte mà không quan tâm đến ký tự nào (nếu có) mà chúng có thể đại diện cho người dùng. Với sed, bạn có thể đạt được như vậy bằng cách sửa chữa các miền địa phương để Ccó LC_ALL=Ccho tất cả sedcác lệnh (mặc dù đó cũng sẽ ảnh hưởng đến ngôn ngữ của thông báo lỗi, nếu có).