2010-05-27 40 views
12

Có cách nào để thay thế một chuỗi như @ hoặc * hoặc ? hoặc & mà không cần phải đặt "\" trước nó?Làm cách nào để thoát khỏi các ký tự đặc biệt để thay thế trong một lớp lót Perl?

Ví dụ:

perl -pe 'next if /^#/; s/\@d\&/new_value/ if /param5/' test 

Trong ví dụ này, tôi cần phải thay thế một @d& với new_value nhưng giá trị cũ có thể chứa bất kỳ ký tự, làm cách nào để thoát khỏi những chữ số mà cần phải được thoát?

+0

http://stackoverflow.com/questions/576435/how-do-i-handle-special-characters- in-a-perl-regex – daxim

Trả lời

7

Bạn có một vài vấn đề:

  1. Bạn đang sử dụng \b sai
  2. Bạn đang thay thế mã với các biến shell
  3. Bạn cần phải trích dẫn metacharacters

Từ perldoc perlre

Một ranh giới từ ("\ b") là một điểm giữa hai nhân vật mà có một "\ w" ở một bên của nó

Cả trong những nhân vật @ hoặc &\w ký tự. Vì vậy, trận đấu của bạn được đảm bảo không thành công. Bạn có thể muốn sử dụng cái gì đó như s/(^|\s)\@d\&(\s|$)/${1}new text$2/

(^|\s) nói để phù hợp với một trong hai đầu của chuỗi (^) hoặc ký tự khoảng trắng (\s).

(\s|$) nói để khớp với phần cuối của chuỗi ($) hoặc ký tự khoảng trắng (\s).

Để giải quyết vấn đề thứ hai, bạn nên sử dụng %ENV.

Để giải quyết vấn đề thứ ba, bạn nên sử dụng các chuỗi thoát \Q and \E để thoát khỏi giá trị trong $ENV{a}.

Đưa nó tất cả cùng nhau chúng ta nhận được:

#!/bin/bash 

export a='@d&' 
export b='new text' 

echo 'param5 @d&' | 
    perl -pe 'next if /^#/; s/(^|\s)\Q$ENV{a}\E(\s|$)/$1$ENV{b}$2/ if /param5/' 

nào in

param5 new text 
+0

rất đẹp xin vui lòng giải thích (^ | \ s) giây tôi sử dụng tập tin không phải bởi echo ..... như perl -i -pe ........ tập tin cần phải chage somthing? – yael

+0

Tùy chọn '-p' sẽ lấy từ STDIN hoặc từ danh sách các tệp được truyền vào dưới dạng đối số, vì vậy bạn nên sử dụng nó theo cách bạn đã làm trước đây. Tôi chỉ sử dụng tiếng vọng cho mục đích trình diễn (tôi thích các ví dụ tự chứa). –

+0

vì vậy tôi có thể sử dụng bất kỳ char nào như & hoặc% hoặc $ hoặc? hoặc * như char mà không có bất kỳ vấn đề gì mục tiêu thay thế các dòng rất lớn với char uniq trong tập tin văn bản waht U nghĩ sao? – yael

10

Như đã thảo luận ở perldoc perlre:

... Hôm nay nó là phổ biến hơn để sử dụng quotemeta() chức năng hay "\ Q" metaquoting dãy thoát để vô hiệu hóa tất cả các ý nghĩa đặc biệt metacharacters' như thế này:

/$unquoted\Q$quoted\E$unquoted/ 

Ghi chú rằng nếu bạn đặt dấu xồ nguợc đen (những người không biến bên trong nội suy) giữa "\ Q" và "\ E", backsl đúp quotish nội suy tro có thể dẫn đến kết quả khó hiểu. Nếu bạn cần sử dụng dấu gạch chéo ngược trong "\ Q ... \ E", hãy tham khảo "Chi tiết Gory phân tích cú pháp cấu trúc được trích dẫn" trong perlop.

Bạn cũng có thể sử dụng một ' như delimiter trong s /// hoạt động để làm cho mọi thứ được phân tích theo nghĩa đen:

my $text = '@'; 
$text =~ s'@'1'; 
print $text; 

Trong ví dụ của bạn, bạn có thể làm (lưu ý các dấu nháy đơn):

perl -pe 's/\b\[email protected]&\E\b/new_value/g if m/param5/ and not /^ *#/' 
+0

có thể cụ thể hơn với ví dụ của tôi: perl -pe "s/\ b \ Q @ f & \ E \ b/new_value/g nếu m/param5/và không/^ * #/" cách shuld tôi thay đổi nó để thay thế @ f & bằng new_value? – yael

+0

về câu trả lời cuối cùng của bạn Tôi không làm việc với kịch bản perl kịch bản của tôi là bash vì vậy tôi không thể sử dụng cú pháp perl – yael

+0

@yael: ví dụ cuối cùng chỉ là một ví dụ. Bạn có thể làm bất cứ điều gì với một onliner perl mà bạn có thể làm với một kịch bản perl thực, và tương tự bạn có thể biến bất kỳ onliner perl thành một kịch bản perl thực (không có gì sai với các kịch bản ngắn!) – Ether

6

Các câu trả lời khác đã đề cập đến câu hỏi, bây giờ đây là vấn đề meta của bạn: Leaning Toothpick Syndrome. Khi dấu phân tách và dấu thoát bắt đầu mờ với nhau:

s/\/foo\/bar\\/\/bar\/baz/ 

Giải pháp là sử dụng dấu tách khác nhau. Bạn có thể sử dụng bất cứ thứ gì, nhưng niềng răng cân bằng hoạt động tốt nhất. Hầu hết các biên tập viên có thể phân tích chúng và bạn thường không phải lo lắng về việc thoát.

s{/foo/bar\\}{/bar/baz} 

Đây là regex của bạn với dấu phân cách dấu ngoặc nhọn.

s{\@d\&}{new_value} 

Dễ dàng hơn nhiều trên các lỗ mắt.

+0

Tôi chưa bao giờ nghe nói về hội chứng tăm. Tuyệt vời là có một cái tên cho sự bất tiện này - tôi luôn luôn sử dụng niềng răng thay vì dấu gạch chéo. Tôi cũng đặt ra thuật ngữ "maven diarrea" cho tất cả các đầu ra lệnh mvn không đầu ra vô nghĩa. Tôi hy vọng rằng thuật ngữ đó bắt được. –

1

Nếu bạn thực sự muốn tránh gõ \ s, hãy đặt chuỗi tìm kiếm của bạn vào một biến và sau đó sử dụng chuỗi đó trong regex của bạn để thay thế. Bạn không cần quotemeta hoặc \Q ... \E trong trường hợp đó. Ví dụ:

my $s = '@d&'; 
s/$s/new_value/g; 

Nếu bạn phải sử dụng điều này trong một one-liner, hãy nhớ rằng bạn sẽ phải thoát khỏi $ s nếu bạn sử dụng "s để chứa mã perl của bạn, hoặc loại bỏ các ' s nếu bạn sử dụng ' s để chứa mã perl của bạn.

+0

Bạn có thể muốn nói: s/\ Q $ s \ E/new_value/g; –

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