2012-01-03 41 views
8

Tôi muốn chỉnh sửa tệp qua tập lệnh sed trong tập lệnh bash. Tôi muốn điều này dễ bảo trì sau này; dễ hiểu và sửa đổi. Chuỗi thay thế trông giống như:Làm cách nào để thoát khỏi dấu gạch chéo ngược trong tập lệnh sed được nhúng trong tập lệnh bash

PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]' 

Trong một thế giới hoàn hảo, nó sẽ như thế này:

sed -i "s/^PS1.*$/PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]'/g" /etc/skel/.bashrc 

Vấn đề là bash đó và sed được tước ra \ đưa ra các kết quả sau đây trong tập tin:

PS1='[e[1;32m][@h W]$[e[0m]' 

Không thể sử dụng báo giá đơn lẻ. Một giải pháp bạo lực là sử dụng lối thoát, nhưng để làm việc này tôi có một đường trông thật xấu xí:

sed -i "s/^PS1.*$/PS1='\\\\[\\\\e[1;32m\\\\][\\\\[email protected]\\\\h \\\\W]\\\\$\\\\[\\\\e[0m\\\\]'/g" /etc/skel/.bashrc 

Tôi muốn tập lệnh có thể đọc được và tự chứa (không sử dụng tệp bên ngoài). Bất kỳ lựa chọn thay thế nào ở trên?

+0

Sử dụng dấu nháy đơn xung quanh mọi thứ như regex trừ khi bạn hoàn toàn cần một số biến nội suy vào chuỗi. Thậm chí sau đó, sử dụng dấu nháy đơn xung quanh hầu hết các regex, và chỉ sử dụng dấu ngoặc kép xung quanh phần đó phải được nội suy. Sử dụng một ví dụ được tạo thành: 'sed -e 's /\.\*'"$ 1"' \ * \ ./ ab '"$ 2"' c '\' 'd /' $ 3' hoặc gì đó dọc theo các dòng đó. Trình tự ''\' '' là cách bạn nhúng một dấu nháy đơn vào dòng lệnh; trích dẫn đơn đầu tiên kết thúc phần trích dẫn một lần hiện tại; dấu gạch chéo ngược trích dẫn nhúng một trích dẫn duy nhất vào chuỗi; trích dẫn đơn thứ ba tiếp tục trích dẫn đơn. –

Trả lời

5

Bản in của Bash có thể thêm các lần thoát cần thiết, để lại chuỗi được chèn vào dưới dạng có thể chỉnh sửa, có thể đọc được.

sed -i "s/^PS1.*$/$(printf "%q" "PS1='\[\e[1;32m\][\[email protected]\h \W]$\[\e[0m\]'")/g" /etc/skel/.bashrc 

Không cố gắng dán tất cả trên một dòng làm cho toàn bộ điều rõ ràng hơn.

REPL=$(printf "%q" "PS1='\[\e[1;32m\][\[email protected]\h \W]$\[\e[0m\]'") 
sed -i "s/^PS1.*$/$REPL/g" /etc/skel/.bashrc 
1

Sử dụng tệp tập lệnh sed có sed -f. Cách thay thế này cũng không đẹp, bởi vì nó có nghĩa là có một tệp bổ sung nằm xung quanh, nhưng ít nhất bạn tránh thoát khỏi vỏ.

+0

Không muốn sử dụng các tệp bên ngoài. – hauptmech

+0

Bạn có thể sử dụng tài liệu ở đây với một số triển khai 'sed', tức là' sed -f - << 'EOF'' – tripleee

4

Điều này có thể làm việc cho bạn:

echo "PS1=abc" | 
sed 's/^PS1.*$/PS1='\''\\[\\e[1;32m\\][\\[email protected]\\h \\W]\\$\\[\\e[0m\\]'\''/' 
PS1='\[\e[1;32m\][\[email protected]\h \W]\$\[\e[0m\]' 
+0

+1 dấu nháy đơn là cách để đi. – tripleee

+0

Tôi tìm thấy các dấu nháy đơn khó chọn, cộng với chuỗi thay thế cần phải được thoát ra mà làm cho nó khó đọc một chút. – hauptmech

1

Làm thế nào về điều này:

sed -i 's/^PS1.*$/PS1=SINGLEQUOTESLASH[SLASHe[1;32mSLASH][[email protected] SLASHW]SLASH$SLASH[SLASHe[0mSLASH]SINGLEQUOTE/g' /etc/skel/.bashrc 
sed -i "s/SINGLEQUOTE/'/g" /etc/skel/.bashrc 
sed -i "s/SLASH/\\/g" /etc/skel/.bashrc 

Làm nó trong hai đèo là kém hiệu quả, nhưng nhiều hơn một vài micro giây là không đáng kể đối với hầu hết mọi người.

+0

Tôi thích nơi này đi nhưng sed cần của \ thoát ... vì vậy nó không thực tế sản xuất đầu ra mong muốn. – hauptmech

+0

@hauptmech Tôi đã chỉnh sửa nó để sử dụng SLASH thay vì '\'. Có vẻ ít dễ đọc hơn một chút. Bạn có thể sử dụng python hoặc perl tốt hơn –

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