Home > Mobile >  How to handle strings that contain negative numbers using regex
How to handle strings that contain negative numbers using regex

Time:05-26

I am using a simple regex [^0-9.] that doesn't match any numbers between 0 to 9 and a period in my given string and matches the rest, and I replace that with empty string and then convert my valid value (integer or double) in string format into an integer or double.

For example:

'123A.478' => '123.478'
'123.48' => '123.48'
'123AX' => '123'

I want to also handle negative valued strings as well i.e. if a string has '-123', I want to retain it. So, I need to convert the strings as follows:

'--123.46' => '-123.46',
'123A-.46' => '123.46',
'-123--.46' => '-123.46', 
'A-123-.46' => '-123.46'

I tried using a quantifier but I was unable to build a correct regex with my existing one.

Is there any way I can achieve this using regex?

CodePudding user response:

You can use

preg_replace('~^(-)|- ~', '$1', preg_replace('~[^\d.-] ~', '', $s))

See the PHP demo:

<?php

$strings = ['--123.46', '123A-.46', '-123--.46', 'A-123-.46'];
foreach ($strings as $s) {
    echo $s . " => " . preg_replace('~^(-)|- ~', '$1', preg_replace('~[^\d.-] ~', '', $s)) . PHP_EOL;
}

Output:

--123.46 => -123.46
123A-.46 => 123.46
-123--.46 => -123.46
A-123-.46 => -123.46

There are two steps:

  • All occurrences of the [^\d.-] pattern (any char other than a digit, dot or hyphen) are removed from the input string and then
  • The ^(-)|- pattern occurrences (the first char in the string that is a hyphen is placed into Capturing group 1 and all other hyphens are just matched) are replaced with $1, Group 1 value (so, all hyphens are removed but the first one in the string).

CodePudding user response:

You might use an alternation to remove the parts from the example strings, and in the replacement use an empty string.

^[^\d\s] (?=-)|[^\d\s.] (?!\d)

Explanation

  • ^ Start of string
  • [^\d\s] Match 1 chars other than a digit or a whitespace char
  • (?=-) Assert a - directly to the right
  • | Or
  • [^\d\s.] Match 1 chars other than a digit, whitespace char or dot
  • (?!\d) Assert not a digit directly to the right

See a regex demo and a PHP demo.

Example code

$strings = [
    "123A.478",
    "123.48",
    "123AX",
    "--123.46",
    "123A-.46",
    "-123--.46",
    "A-123-.46"
];

$pattern = '/^[^\d\s] (?=-)|[^\d\s.] (?!\d)/';

foreach ($strings as $str) {
    echo preg_replace($pattern, "", $str) . PHP_EOL;
}

Output

123.478
123.48
123
-123.46
123.46
-123.46
-123.46
  • Related