2015-01-05 14 views
45

Tôi thực sự biết câu trả lời cho câu hỏi này, tuy nhiên nhiều hơn một lần tôi đã nhìn thấy một số đồng nghiệp của tôi bị mắc kẹt về vấn đề này, vì vậy tôi nghĩ rằng nó sẽ là đáng giá để tài liệu trên VÌ THẾ. Nếu câu hỏi đã tồn tại, tôi sẽ sẵn sàng xóa nó đi.Làm thế nào để vượt qua một biến có chứa dấu gạch chéo để sed

Vì vậy, ở đây nó đi ...

Làm thế nào để bạn vượt qua một biến có chứa dấu gạch chéo như một mô hình để sed.

Ví dụ, nếu tôi có biến sau đây:

var="/Users/Documents/name/file" 

Tôi muốn vượt qua nó để sed như vậy:

sed "s/$var/replace/g" $file 

Tuy nhiên tôi nhận được lỗi. Làm thế nào tôi có thể phá vỡ vấn đề?

Trả lời

79

Sử dụng một delimiter regex thay thế như sed cho phép bạn sử dụng bất kỳ dấu phân cách (bao gồm ký tự điều khiển):

sed "s~$var~replace~g" $file 
+1

đề xuất Không làm việc. Tôi thử sed -i "s ~ blah ~ $ var ~ g file" và nhận được: "sed -e expression # 1, char 70: unterminated' s 'command ". Tôi đã xác nhận rằng thủ phạm là một dấu gạch chéo trong $ var. Các biến thể của giải pháp này là tất cả các nơi và không ai trong số họ làm việc. Đã cập nhật gần đây sed? Tôi đang trên v4.2.2 trên Ubuntu 14.04.4 LTS. –

+0

Điều đó phụ thuộc vào giá trị của '$ var' – anubhava

+1

Không hoạt động với ~ như @PaulEricson đã quan sát, nhưng vẫn hoạt động với | –

23

Một bash câu trả lời tinh khiết: sử dụng parameter expansion để xuyệc ngược-thoát khỏi bất kỳ dấu gạch chéo trong biến:

var="/Users/Documents/name/file" 
sed "s/${var//\//\\/}/replace/g" $file 
+0

Đây là một cách hay vì bạn không phải lúc nào cũng biết ký tự nào chứa biến. Vì vậy, bạn luôn có thể thoát khỏi dấu phân cách sed nếu có một nghi ngờ. Ví dụ: sed "s: $ {var //:/\\:}: thay thế: g" $ file –

+0

Đẹp. Thực hiện một số kịch bản đổi tên của tôi sạch hơn nhiều. – DevNull

+0

Điều đó đã giúp tôi rất nhiều cảm ơn bạn :) – gabtzi

21

Một cách khác để làm điều đó, mặc dù xấu hơn câu trả lời của anubhava, là bằng cách thoát tất cả các dấu gạch chéo ngược trong var bằng cách sử dụng một sốkhác 210 lệnh:

var=$(echo "$var" | sed 's/\//\\\//g') 

sau đó, điều này sẽ làm việc:

sed "s/$var/replace/g" $file 
5

Sử dụng / trong sed như một dấu phân cách sẽ xung đột với các dấu gạch chéo trong biến khi thay và kết quả là bạn sẽ nhận được một lỗi. Một cách để vượt qua điều này là sử dụng một dấu phân cách khác là duy nhất từ ​​bất kỳ ký tự nào có trong biến đó.

var="/Users/Documents/name/file" 

bạn có thể sử dụng ký tự octothorpe mà phù hợp với dịp này (hoặc bất kỳ ký tự khác mà không phải là một / để dễ sử dụng)

sed "s#$var#replace#g" 

hoặc

sed 's#$'$var'#replace#g' 

này là phù hợp khi biến không chứa dấu cách

hoặc

sed 's#$"'$var'"#replace#g' 

Sẽ khôn ngoan hơn khi sử dụng ở trên vì chúng tôi chỉ muốn thay thế bất kỳ thứ gì trong biến đó chỉ so với việc trích dẫn kép toàn bộ lệnh có thể khiến shell của bạn can thiệp vào bất kỳ ký tự nào cho nhân vật.

+0

Không hoạt động. Tôi thử sed -i "s ~ blah ~ $ var ~ g file" và nhận được: "sed -e expression # 1, char 70: unterminated' s 'command ". Tôi đã xác nhận rằng thủ phạm là một dấu gạch chéo trong $ var. Các biến thể của giải pháp này là tất cả các nơi và không ai trong số họ làm việc. Đã cập nhật gần đây sed? Tôi đang trên v4.2.2 trên Ubuntu 14.04.4 LTS. –

1

Dấu phân cách thay thế chỉ hoạt động khi có nhu cầu tìm kiếm và thay thế. Trong các trường hợp như nơi cần xóa các dòng khỏi tệp dựa trên từ chứa/(ví dụ: /dev/sda1), nó sẽ không hoạt động. Đối với e.g:

var1=/dev/sda1 
sed -i ":$var1:d" $file 

Tôi muốn đi với giải pháp bởi @Bolboa

Các vấn đề liên quan