我有一个字符串
$test = 'xyz45sd2-32d34-sd23-456562.abc.com'
目标是获得$ 1 = 23和$ 2 = 45,即最后-
两侧的数字位数相同。请注意,位数是可变的,不一定是2。
我尝试了以下内容:
$test1 =~ s/.*(\d+)-(\d+).*//;
但是
答案 0 :(得分:1)
你可以试试这个正则表达式
if($test1 =~ m/(\S+)-(\S+)-([a-z]*)(\d+)-(\d\d)(\d+).*/)
{
print $4,"|",$5;
}
我认为你只需要456562的前2个答案
答案 1 :(得分:1)
perl -e '"xyz45sd2-32d34-sd23-456562.abc.com" =~ /(\d{2})-(\d{2})\d*(?=\.)/; print "$1\n$2\n"'
答案 2 :(得分:1)
此其他条目确认正则表达式不计算: How to match word where count of characters same
基于GreatBigBore的想法,如果计数的上限,则可以尝试使用或运算符|。这只符合您查找匹配的要求;根据匹配的计数,匹配将在不同的箱中。只有一个案例正确地将它们放在$ 1和$ 2中。
(\d{3})-(\d{3})|(\d{2})-(\d{2})|(\d{1})-(\d{1})
但是,如果你将结果捕获连接为$ 1 $ 3 $ 5和$ 2 $ 4 $ 6,你将有效地得到你想要的2个刺。
另一个想法是迭代操作,你可以通过增加数字来重复搜索字符串,直到匹配失败。 (\d{1})-(\d{1})
,(\d{2})-(\d{2})
...
二进制搜索让人联想到它是一个O {ln(N)},N是捕获长度的上限。
答案 3 :(得分:1)
使用正则表达式无法找到您正在寻找的内容。
正则表达式(顾名思义)是Regular languages(Chomsky Heirarchy中Type-3 grammars
)的简洁表示。
使用正则表达式无法找到您正在寻找的内容,因为您正试图写出一个维持某种计数的表达式(除了beginning
和{{1之外的某些上下文信息) }})。这种行为无法建模为 DFA (实际上是任何有限自动机)。 end
language
是否为regular
的非正式证明是存在接受该语言的 DFA 。由于这种上下文信息无法在 DFA 中建模,因此相互矛盾,您无法为您的问题编写正则表达式。
my ($lhs,$rhs) = $test =~ /^[^-]+-[^-]+-([^-]+)-([^-.]+)\S+/;
# Alernatively and faster
my (undef,undef,$lhs,$rhs) = split /-/, $test;
# Rest is common, no matter how $lhs and $rhs is extracted.
my @left = reverse split //, $lhs;
my @right = split //, $rhs;
my $i;
for($i=0; exists($left[$i]) and exists($right[$i]) and $left[$i] =~ /\d/ and $right[$i] =~ /\d/ ; ++$i){}
--$i;
$lhs= join "", reverse @left[0..$i];
$rhs= join "", @right[0..$i];
print $lhs, "\t", $rhs, "\n";
修改:通过使用正则表达式提取$lhs
和$rhs
所需的数字部分而不是{{1},可以改进我的解决方案},split
和reverse
。
答案 4 :(得分:0)
正如@Samveen所说,在纯正则表达式中技术上不可能做到这一点
和@Samveen解决方案一样,这是另一个版本
#get left and right
my (undef,undef,$left,$right) = split /-/, $test;
#get left numbers
$left =~ s/.*?(\d+)$/$1/;
##get right numbers
$right =~ s/^(\d+).*/$1/;
##get length of both
my $right_length = length $right;
my $left_length = length $left;
if ($right_length > $left_length){
#make right length as same as left length
$right =~ s/(\d{$left_length}).*/$1/;
} else {
#make left length as same as right length
$left =~ s/.*(\d{$right_length})/$1/;
}
print $left, "\t", $right, "\n";