[英]Using <> and regex to search and replace elements in text files
我正在通過Learning Perl ,第9章“使用正則表達式處理文本”。
這是章節結束練習中的兩個:
編寫一個程序,為目前為止的所有練習答案添加一個版權行,在'shebang'行之后立即在
## Copyright (c) 20XX by Yours Truly
中添加## Copyright (c) 20XX by Yours Truly
。 假設將使用文件名調用程序,以便在命令行上進行編輯。修改以前的程序,使其不編輯已包含版權行的文件。 作為提示,您可能需要知道菱形運算符讀取的文件名是$ ARGV。
這是我嘗試的解決方案:
#!/usr/bin/env perl
use 5.014;
use warnings;
my $shebang = '(#!/usr/bin/env perl|#!/usr/bin/perl)';
my $copyright = '# Copyright (c) 20XX Yours Truly';
$^I = ".bak";
while (<>) {
unless (/$copyright/mi) {
s/($shebang)/$1\n$copyright/mig;
}
print;
}
使用perl ch9.pl sample_perl_script.pl
在命令行上運行。
我的目標是:
<>
。 unless { ... }
)。 這適用於問題的第一部分(添加版權線)但不適用於第二部分(檢查以確保版權尚不存在)。
我的問題是:為什么? 為什么在我運行程序時完全忽略了unless
?
我偷看了附錄,本書提出的解決方案是創建一個哈希來跟蹤$ARGV
文件名,並將文件傳遞兩次 。 首先要刪除已經有版權聲明的文件,然后執行搜索/替換。 像這樣:
my %do_these;
foreach (@ARGV) {
$do_these{$_} = 1;
}
while (<>) {
if (/\A## Copyright/) {
delete $do_these{$ARGV};
}
}
@ARGV = sort keys %do_these;
$^I = ".bak";
while (<>) {
if (/\A#!/) {
$_ .= "## Copyright (c) 20XX by Yours Truly\n";
}
print;
}
當然,這有效,但似乎是工作的兩倍。 我試圖通過我的方法在單個while (<>) { ... }
循環中找到一種方法來實現這一點,並且更好地理解鑽石算子的工作原理。
如果我的方法完全偏離基礎,請解釋原因並且不要放過我的感受。 我對比我的自我更全面的了解更感興趣。
你的書的方法是愚蠢的。 實際上,我認為perl正在bar,因為你的版權聲明有像(
。
你想要的是quotemeta
函數。 鏈接
我會改變你的程序:
while (<>) {
my $copyright2 = quotemeta $copyright;
unless (/$copyright2/mi) {
s/($shebang)/$1\n$copyright/mig;
}
print;
}
如果這不起作用,請道歉。 我寫perl已經有一段時間了。
你的unless
不起作用,因為版權與shebang不在同一條線上。 鑽石運算符讀取一行直到$/
的第一個值,默認情況下是換行符。 您的程序將在不包含版權的所有行上執行替換。
由於這是perl,因此有很多方法可以解決它。 最直接的方法可能是取消設置$/
並啜飲文件(將其全部讀成一行)。 這樣,如果文件的第二行有版權聲明,您可以立即查看。 例如:
local $/; # slurp the file
while (<>) {
s/^.*\n\K(?!\Q$copyright\E)/$copyright/; # negative lookahead assertion
print;
}
您還可以直接在文件中檢查第2行,而不會詆毀文件:
while (<>) {
if ($. == 2) {
unless (/\Q$copyright/) {
print "$copyright\n";
}
}
print;
close ARGV if eof; # this will reset the line counter $.
}
請注意,Nick ODell是正確的,您的版權字符串包含必須轉義的元字符(即括號)。 我在上面使用了\\Q ... \\E
轉義序列。
另請注意,您不需要非常具體地檢查shebang,這更有可能在稍微不同的線路上絆倒您。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.