2009-06-23 39 views
44

Tôi biết loại câu hỏi này đã được hỏi nhiều lần trước đây. Lý do tại sao tôi đến đây một lần nữa là tôi cảm thấy như tôi đã bỏ lỡ một cái gì đó đơn giản và cơ bản.Tìm kiếm nhiều dòng thay thế bằng Perl

Có thể thực hiện loại thói quen tìm kiếm thay thế này tốt hơn không. Ví dụ: không mở cùng một tệp hai lần. Ngoài ra tốc độ liên quan đến lời khuyên được chào đón.

Hãy lưu ý rằng điều này làm việc với các kết hợp nhiều dòng và thay thế các chuỗi nhiều dòng.

#!/bin/perl -w -0777 

local $/ = undef; 

open INFILE, $full_file_path or die "Could not open file. $!"; 
$string = <INFILE>; 
close INFILE; 

$string =~ s/START.*STOP/$replace_string/sm; 

open OUTFILE, ">", $full_file_path or die "Could not open file. $!"; 
print OUTFILE ($string); 
close OUTFILE; 
+0

Dường như bạn đang cố gắng chỉnh sửa tệp tại chỗ. Đó là, mở nó để đọc cũng như để viết. Đúng không? –

+0

Có, chỉnh sửa tệp tại chỗ. Đó là trường hợp sử dụng phổ biến nhất đối với tôi. – user44556

Trả lời

80

Loại tìm kiếm và thay thế có thể được thực hiện với một lớp lót như -

perl -i -pe 's/START.*STOP/replace_string/g' file_to_change 

Để biết thêm cách để thực hiện điều tương tự kiểm tra thread này. Để xử lý nhiều đường tìm kiếm sử dụng lệnh sau -

perl -i -pe 'BEGIN{undef $/;} s/START.*STOP/replace_string/smg' file_to_change 

Để chuyển đổi các mã sau đây từ một lớp lót cho một chương trình perl có một cái nhìn tại perlrun documentation.

Nếu bạn thực sự thấy cần phải chuyển đổi điều này thành một chương trình làm việc thì chỉ cần để Perl xử lý việc mở/đóng tệp cho bạn.

#!/usr/bin/perl -pi 
#multi-line in place substitute - subs.pl 
use strict; 
use warnings; 

BEGIN {undef $/;} 

s/START.*STOP/replace_string/smg; 

Sau đó bạn có thể gọi kịch bản với tên tập tin như là đối số đầu tiên

$perl subs.pl file_to_change 

Nếu bạn muốn có một kịch bản meatier hơn nơi bạn có thể xử lý các tập tin mở/hoạt động chặt chẽ (chúng ta không yêu tất cả những câu lệnh 'chết' đó) sau đó xem xét ví dụ trong perlrun dưới khóa chuyển đổi -i [extension].

+0

Làm thế nào để bạn chuyển đổi một lớp lót này thành mã perl thực? Nó có xấu không? – user44556

+1

Và điều này dường như không hoạt động với kết hợp nhiều dòng – user44556

+0

Đúng vậy, vì điều này hoạt động trên từng dòng riêng. –

2

Xét rằng bạn húp trong toàn bộ nội dung của tập tin với:

local $/ = undef; 

open INFILE, $full_file_path or die "Could not open file. $!"; 
$string = <INFILE>; 
close INFILE; 

Và sau đó làm tất cả việc xử lý với $string, không có mối liên hệ giữa cách bạn xử lý các tập tin và cách bạn xử lý các nội dung. Bạn sẽ gặp sự cố nếu bạn mở tệp để viết trước khi bạn đọc xong, vì mở tệp để ghi sẽ tạo tệp mới, loại bỏ các nội dung trước đó.

Nếu tất cả những gì bạn đang cố gắng làm là lưu vào các câu lệnh mở/đóng, hãy thực hiện như Jonathan Leffer suggested. Nếu câu hỏi của bạn về tìm kiếm và thay thế nhiều dòng, thì hãy làm rõ vấn đề là gì.

+0

Đó là về tìm kiếm đa nguyên chung và thay thế. Có thực sự tốt mà tôi mở cùng một con trỏ tập tin một lần nữa ngay cả khi tập tin là rất lớn? Trong một lớp lót có vẻ như không cần phải mở cùng một tệp hai lần. Tôi vẫn còn thiếu cái gì đó ở đây. Có lẽ tôi nên xem ví dụ của Jonathan trong thực tế. – user44556

+0

tạo trình xử lý tệp không có gì để làm với kích thước của tệp. Nó chỉ là một con trỏ. Hành động mở tệp không ngụ ý đọc nội dung của nó. –

+0

Tôi nghĩ rằng đây là một nơi nào đó gần sự hiểu lầm của tôi. Làm thế nào để mở cùng một tệp một lần cho cả đọc và viết khi đọc có nghĩa là thao tác cần thiết để thực hiện nó để tìm các kết quả phù hợp? – user44556

1

Kéo câu trả lời ngắn từ nhận xét, cho bất kỳ ai đang tìm kiếm một lớp lót nhanh và lý do Perl bỏ qua tùy chọn RegEx của họ từ dòng lệnh.

perl -0pe 's/search/replace/gms' file

Nếu không có sự tranh luận -0, Perl xử lý dữ liệu line-by-line, gây ra các tìm kiếm multiline thất bại.

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