让我们说,我有一个这样的文件(它不是实际的内容,而是hexdump):
0000000 \r \n \r \n T h i s i s a f i
0000010 l e \r \n \r \n H e r
0000020 e ' s s o m e t e x t \r \n
000002f
如果我运行以下内容:
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
$_ = read_file("file.txt");
s/^\s*$//mg;
print;
产生的输出是:
0000000 \n T h i s i s a f i l e \r
0000010 \n \n H e r e ' s s o m e t e
0000020 x t \r \n
显然,空白行没有被删除。
有谁可以指出我做错了什么?
答案 0 :(得分:6)
在正则表达式中,$
断言可能有点令人困惑。根据文档,它“匹配[es]行的结尾(或在结尾的换行符之前)”。所以它的行为大致类似于
(?=\n\z)|\z
使用/m
修饰符,此更改为
(?=\n)|\z
这意味着匹配的子字符串中不包含\n
。你想要:
s/^\s*\n//mg;
现在代码中仍有一些问题需要解决。主要是,立即读取整个文件并运行正则表达式是没有意义的。相反,我会这样做:
use strict; use warnings; use autodie;
open my $fh, "<", "file.txt";
while (<$fh>) {
print if /\S/; # print if this line contains at least one non-space character
# this elegantly skips whitespace-only lines.
}
这假设行结尾完全由空格字符组成,以\n
结尾。这适用于\r\n
和\n
行结尾。否则,分配自定义行结尾,如
local $/ = local $\ = "\r\n"; # input and output line endings
while (<$fh>) {
chomp; # remove line endings
print if /\S/; # print adds the line ending again.
}
答案 1 :(得分:0)
我自己的多线比赛没有成功,所以我再次将内容分成几行:
#!/usr/bin/perl
use strict;
use warnings;
use File::Slurp;
my $content = read_file("test.txt"); # You should'nt set $_ explicitely
foreach (split(/\r\n/,$content)){
if ($_ =~ /\S/){
print $_ . "\n";
}
}