我知道除了使用正则表达式的给定字符之外,很容易匹配任何内容。
$text = "ab ac ad";
$text =~ s/[^c]*//g; # Match anything, except c.
$text is now "c".
我不知道如何“除”字符串而不是字符。我怎么能“匹配任何东西,除了'ac'”?尝试[^(ac)]和[^“ac”]但没有成功。
有可能吗?
答案 0 :(得分:5)
以下解决了巴特K所述的第二种意义所理解的问题。评论:
>> $text='ab ac ad';
>> $text =~ s/(ac)|./\1/g;
>> print $text;
ac
此外,'abacadac'
- > 'acac'
应该注意的是,在大多数实际应用中,负面前瞻证明比这种方法更有用。
答案 1 :(得分:2)
如果你只想检查字符串是否不包含“ac”,只需使用否定。
$text = "ab ac ad";
print "ac not found" if $text !~ /ac/;
或
print "ac not found" unless $text =~ /ac/;
答案 2 :(得分:2)
$text =~ s/[^c]*//g; // Match anything, except c.
<强> @ssn 下, 关于你的问题的一些评论:
我怎么能“匹配任何东西,除了 'ac'“?试过[^(ac)]和[^”ac“] 没有成功。
请阅读有关字符类的文档(请参阅命令行中的“perldoc perlre”或http://perldoc.perl.org/perlre.html在线) - 您会看到它指出方括号内的字符列表RE将“匹配列表中的任何字符”。含义顺序不相关,没有“字符串”,只有字符列表。 “()”和双引号在方括号内也没有特殊含义。
现在我不确定你为什么要谈论匹配,然后给出一个替代的例子。但是要查看字符串是否与子字符串“ac”不匹配,您只需要取消匹配:
use strict; use warnings;
my $text = "ab ac ad";
if ($text !~ m/ac/) {
print "Yey the text doesn't match 'ac'!\n"; # this shouldn't be printed
}
假设您有一个文本字符串,其中嵌入了多次出现的子字符串。如果您只想要围绕子字符串的文本,只需删除所有出现的子字符串:
$text =~ s/ac//g;
如果你想反过来 - 除了所有出现的子字符串之外的所有文字都删除了,我会建议像:
use strict; use warnings;
my $text = "ab ac ad ac ae";
my $sub_str = "ac";
my @captured = $text =~ m/($sub_str)/g;
my $num = scalar @captured;
print (($sub_str x $num) . "\n");
这基本上计算子字符串在文本中出现的次数,并使用“x”运算符打印子字符串的次数。不是很优雅,我相信Perl-guru可以提供更好的东西。
<强> @ennuikiller 强>:
my $text = "ab ac ad";
$text !~ s/(ac)//g; # Match anything, except ac.
这是不正确的,因为它会在“使用警告”下生成一个警告(在无效上下文中使用否定模式绑定(!〜))并且除了从文本中删除所有子串“ac”之外什么都不做,这可以更简单地写成我在上面写的:
$text =~ s/ac//g;
答案 3 :(得分:2)
更新:在对您的问题发表评论时,您提到要清除维基标记并删除{{
... }}
的平衡序列。 Perl FAQ的第6部分涵盖了这一点:Can I use Perl regular expressions to match balanced text?
考虑以下计划:
#! /usr/bin/perl
use warnings;
use strict;
use Text::Balanced qw/ extract_tagged /;
# for demo only
*ARGV = *DATA;
while (<>) {
if (s/^(.+?)(?=\{\{)//) {
print $1;
my(undef,$after) = extract_tagged $_, "{{" => "}}";
if (defined $after) {
$_ = $after;
redo;
}
}
print;
}
__DATA__
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. {{delete me}} Sed quis
nulla ut dolor {{me too}} fringilla
mollis {{ quis {{ ac }} erat.
其输出:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quis nulla ut dolor fringilla mollis {{ quis erat.
对于您的特定示例,您可以使用
$text =~ s/[^ac]|a(?!c)|(?<!a)c//g;
也就是说,只有当a
或c
不属于ac
序列时,才会删除它。
一般来说,这对于正则表达式来说很棘手。
假设您不希望foo
后跟可选空格,然后bar
$str
。通常,单独检查更清晰,更容易。例如:
die "invalid string ($str)"
if $str =~ /^.*foo\s*bar/;
你可能也对an answer to a similar question感兴趣,我在那里写了
my $nofoo = qr/
( [^f] |
f (?! o) |
fo (?! o \s* bar)
)*
/x;
my $pattern = qr/^ $nofoo bar /x;
要了解并发症,请阅读Mark Dominus的How Regexes Work。引擎将正则表达式编译为状态机。当匹配时,它将输入字符串提供给状态机并检查状态机是否处于接受状态。因此,要排除字符串,您必须指定一台接受除特定序列之外的所有输入的计算机。
可能有帮助的是/v
正则表达式开关,它像往常一样创建状态机,但随后补充所有状态的接受状态位。与单独的检查相比,这很难说这是否真的有用,因为/v
正则表达式可能会以不同的方式让人感到惊讶。
如果您对理论细节感兴趣,请参阅Peter Linz的An Introduction to Formal Languages and Automata。
答案 4 :(得分:1)
你可以使用index()
$text = "ab ac ad";
print "ac not found" if ( index($text,"ac") == -1 );
答案 5 :(得分:0)
您可以轻松修改此正则表达式。
use Test::More 0.88;
#Match any whole text that does not contain a string
my $re=qr/^(?:(?!ac).)*$/;
my $str='ab ac ad';
ok(!$str=~$re);
$str='ab af ad';
ok($str=~$re);
done_testing();