Ish Thomas
Ish Thomas

Reputation: 2440

How to catch a dot in Perl regex?

I'm trying to execute this lines of code:

  my $test = 'test .15oz test';
  $test =~ /([\d]+)([\.]?[\d]+)*oz\b/;
  print("test=$1\n");

The output of this is:

  test=15

I want to catch that dot. What am I doing wrong? The best would be to catch 0.15 somehow, but for now I can't even get a dot.

Any help with getting 0.15 from regex would be appreciated, so:

0.15 -> 0.15

.15 -> 0.15

..15 -> 0.15

0.0.0.15 -> 0.15

000.15 -> 0.15

15 -> 15

I tried also:

$test =~ /([\d]+)(\.?[\d]+)*oz\b/;
$test =~ /([\d]+)([.]?[\d]+)*oz\b/;

But with no success. Still getting "15".

Upvotes: 3

Views: 2506

Answers (2)

ikegami
ikegami

Reputation: 385897

The strings you want to match are matched by

(?:\d+(?:\.\d+)?|\.\d+)oz

(Wiktor Stribiżew posted something shorter, but far less efficient.)

So you want

if ( my ($match) = $test =~ /(\d+(?:\.\d+)?|\.\d+)oz/ ) {
   say $match;
}

You can't possibly match 0.15 if your input .15 or ..15. Simply fix up the string independently of the match.

$match = "0".$match if $match =~ /^\./;

Similarly, trimming leading zeros is best done outside of the match.

$match =~ s/^0+(?!\.)//;

All together, we get

if ( my ($match) = $test =~ /(\d+(?:\.\d+)?|\.\d+)oz/ ) {
   $match =~ s/^0+(?!\.)//;
   $match = "0".$match if $match =~ /^\./;
   say $match;
}

Upvotes: 4

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626929

You are using the first capturing group. In your pattern, ([\d]+)([\.]?[\d]+)*oz\b, the first capturing group matches one or more digits. To capture the whole float or integer number before oz, use

$test =~ /(\d*\.?\d+)oz\b/;
          ^         ^

where \d*\.?\d+ will match 0+ digits, an optional dot (note it is escaped outside a character class) and 1+ digits.

Upvotes: 1

Related Questions