我想编写一个删除双标签,换行符和空格的perl脚本。
到目前为止我所拥有的是:
$txt=~s/\r//gs;
$txt=~s/ +/ /gs;
$txt=~s/\t+/\t/gs;
$txt=~s/[\t\n]*\n/\n/gs;
$txt=~s/\n+/\n/gs;
但是, 这不美。应该可以用更少的正则表达式做到这一点。 它只是不起作用,我真的不知道为什么。它留下了一些双标签,空格和空行(即只有标签或空格的行)
我可以用一段时间解决它,但这非常缓慢和丑陋。
有什么建议吗?
答案 0 :(得分:3)
你有一些混合的东西,并不是所有的东西都符合你所说的。让我们分解你所拥有的东西然后你可以从那里工作到你想要的东西。
$txt=~s/\r//s; # removes a single \r from the line. Did you mean to use g on this one?
$txt=~s/[\t ]\n//s; # match a single \t OR space right before a \n, and remove.
$txt=~s/ +/ /gs;# match at least 2 spaces, replace with a single space
$txt=~s/\t+/ /gs;# match at least 2 \t, replace with a single space
$txt=~s/\n /\n/s;# remove a space immediately following a \n
$txt=~s/\t /\t/s;# remove a space immediately following a \t
$txt=~s/\n+/ /gs;# match at least 2 \n, replace them all with a single space
我觉得根本不是你想要完成的事情。
我真的不明白你想做什么。我阅读你声明的意图的方式,我认为你想用单个标签替换所有双标签,所有双行换行用单换行,所有双空格用单个空格。我进一步猜测你想要真正运行这些角色,而不仅仅是双打。这是我刚才所说的正则表达式,希望能给你一些东西: (我也删除了所有\ r)。
$txt=~s/\r//gs;# remove all \r
$txt=~s/\t+/\t/gs;# replace all runs of > 1 tab with a single tab
$txt=~s/\n+/\n/gs;# replace all runs of > 1 \n with a single \n
$txt=~s/ +/ /gs;# replace all runs of > 1 space with a single space
鉴于您尝试的正则表达似乎与我阅读您所陈述的愿望的方式不符,我怀疑您对此处真正想做的事情有些模糊。你可能想进一步思考你想要完成什么,这应该有助于正则表达式变得更加清晰。
答案 1 :(得分:2)
当我试着为你做一个快速真实的答案时,你看过文档(不,我不只是说rtfm)。 perldoc
是一个很棒的工具,有一些有用的信息,我建议您perldoc perlrequick
和perldoc perlreref
让您前进。
首先,您可能会发现将长文本拆分为多行并分别对这些行进行操作然后再次加入它们会更容易。此外,如果我们创建一个新数组来存储要连接的结果,我们可以轻松地排除空行。
最后,让我感到震惊的是,在操作一长串文本时,该文本很可能是您脚本的外部文本。如果你真的打开一个文件并将其汇总成一个变量,你可以更容易地做我留下的评论块。要使用此方法注释第一个块并删除第二个块上的注释,第三个块将保留为任一方法。我包括这个因为如果你真的在读取文件然后拆分它,它会省去很多工作,只需逐行读取它。如果需要,您可以将其写入另一个文件。
#!/usr/bin/env perl
use strict;
use warnings;
my @return_lines;
### Begin "text in script" Method ###
my $txt = <<END;
hello world
hello world
hello world
hello world
END
#note last two are to test removing spaces after tabs
my @lines = split(/\n/, $txt);
foreach my $line (@lines) {
### Begin "text in external file" Method (commented) ###
#my $filename = 'file.txt';
#open( my $filehandle, '<', $filename);
#while (<$filehandle>) {
# my $line = $_;
### Script continues for either input method ###
$line =~ s/^\s*//; #remove leading whitespace
$line =~ s/\s*$//; #remove trailing whitespace
$line =~ s/\ {2,}/ /g; #remove multiple literal spaces
$line =~ s/\t{2,}/\t/g; #remove excess tabs (is this what you meant?)
$line =~ s/(?<=\t)\ *//g; #remove any spaces after a tab
push @return_lines, $line unless $line=~/^\s*$/; #remove empty lines
}
my $return_txt = join("\n", @return_lines) . "\n";
print $return_txt;
答案 2 :(得分:2)
我不确定您的确切要求,但这里有一些提示可能会让您前进:
将所有空白区域压缩到空格(可能太强大了!)
$txt=~s/\s+/ /g ;
删除行首
时的任何空格$txt=~s/^ +//gm ;
将多个标签压缩到空格
$txt=~s/\t+/ /g ;
答案 3 :(得分:1)
这有点不清楚。
如果您有ab TABcTABTAB \n\n
这样的行,那么您想要什么?我正在阅读上面的ab c\n
? - DVK 1分钟前编辑
换句话说,你想要它是否正确:
行中间的所有空格(例如任意数量的空格和制表符)都转换为单个空格?
删除了行开头或结尾处的所有空格(换行除外)?
完全删除空行?
$s =~ s/[\t ]+$//ms; # Remove ending spaces/tabs
$s =~ s/^[\t ]+//ms; # Remove starting spaces/tabs
$s =~ s/[\t ]+/ /ms; # Replace duplicate whitespace mid-string with 1 space
$s =~ s/^$//ms; # Remove completely empty lines
请注意,我使用了“/ ms”修改器(有关详细信息,请阅读perdoc perlre),以便我可以在多行字符串中使用行锚的开始/结束。