use strict;
use warnings;
use Test::More;
my @good = (
'1234',
'5566foo bar',
'baz9980'
);
my @bad = (
'a',
'12',
'12.4',
'-124baz',
'2018-01-01'
);
my $re = qr/\d{4}(?!-)/a;
plan tests => @good + @bad;
for my $str (@good) {
like ($str, $re, "$str matched");
}
for my $str (@bad) {
unlike ($str, $re, "$str not matched");
}
| [reply] [d/l] |
look for the 4 digits unless it has a dash after it
There's a good reference in the monastery. You want negative look-ahead. I also recommend not using \d. Under Unicode there are MANY numbers that will match that do not conform to the 0..9 I think you expect.
/\b[0-9]{4}\b(?!-)/
| [reply] [d/l] [select] |
In addition to the negative look-ahead, you must escape all the html mark-up characters which have special meaning in a substitution string. Normally you could use \Q and \E, but in this case, they would escape the $1's which must have their regex meaning. You also need a \d in the negative look-ahead to prevent matching the first three digits of the year. You probably should repeat this test with more realistic strings, but I think this covers the important cases. (All six cases pass)
use strict;
use warnings;
use Test::Simple tests => 6;
my $digits_4 = qr/(\d{3,4})(?![\d-])/;
my $hyper = '<hyper>';
my @cases = (
# Input Expected output
['2018-1-1 1234', '2018-1-1 <a href="script.pl?do_what=view&unit
+=1234"><b>1234</b></a>' ],
['2018-1-1 567', '2018-1-1 <a href="script.pl?do_what=view&unit
+=567"><b>567</b></a>' ],
['2018-1-1 abcd', '2018-1-1 abcd' ],
['2018-1-1 1234 x', '2018-1-1 <a href="script.pl?do_what=view&unit
+=1234"><b>1234</b></a> x' ],
['2018-1-1 567 x', '2018-1-1 <a href="script.pl?do_what=view&unit
+=567"><b>567</b></a> x' ],
['2018-1-1 abcd x', '2018-1-1 abcd x' ],
);
foreach my $case (@cases) {
$case->[0] =~ s{$digits_4}
{\<a href\=\"script\.pl\?do\_what\=view\&unit\=$1\"\>\<b\>$1\<
+\/b\>\<\/a\>};
ok( $case->[0] eq $case->[1]);
}
| [reply] [d/l] |