Regex in PHP to strip everything except digits and decimal point and truncate string to two digits after the decimal point

huangapple go评论49阅读模式
英文:

Regex in PHP to strip everything except digits and decimal point and truncate string to two digits after the decimal point

问题

In PHP, you can use the following regular expression and replacement string with preg_replace() to achieve the desired result:

Regular Expression:

/^.*?(\d+(?:\.\d{0,2})?).*$/

Replacement String:

$1

Here's how you can use it:

$input_string = "*$234.345";
$output = preg_replace('/^.*?(\d+(?:\.\d{0,2})?).*$/', '$1', $input_string);
echo $output; // Output will be '234.34'

This regular expression will match and capture the first encountered decimal number with up to two decimal places in the input string and replace the entire input string with that captured value.

英文:

What regex in PHP would strip all characters from any input string except digits and the first encountered decimal point, and truncate everything to two digits after the first encountered decimal point (if more than one is present).
The input string should be interpreted from left to right, so string such as $34.455r.4r45,45.45 should yield the following output 34.45.
Also, "any input string" means that strings with no dots, or no digits, and those having whatever other combination of characters are also possible as an input.

For example:

Input string                                Desired output
*$234.345                                   => 234.34
(9.9)                                       => 9.9
$34.455r.4r45,45.45                         => 34.45
2023-05-29 03:40:11Z, License: CC BY-SA 4.0 => 202305290340114.0
9.95,6.432,0.3                              => 9.95
po2iaw5e.ro1i7im8jjks;fl32;i.u12ma          => 25.17
oias25.spkks                                => 25.
4545                                        => 4545
oi.as2.5.6spkks                             => .25
oi.as..spkks                                => .

I tried this expression but it doesn't work

preg_replace('/^\d+(\.\d{0,2})?$/', '', $input_string);

I'm looking for a solution that is a single regular expression and replacement string to be used in one call to preg_replace().

答案1

得分: 1

以下是翻译好的部分:

你可以使用以下的 preg_replace() 调用来替换输入内容为你所寻找的数字:

preg_replace('~[^\d.]+|(\.)\D*(\d?)\D*(\d?).*~', '$1$2$3', $input_string);

正则表达式替换的工作方式如下:

  • 第一部分 [^\d.]+ 很简单,删除所有不是数字或点的字符,并使用捕获组 $1$2$3 进行替换。但由于在正则表达式的这一部分中没有捕获任何内容,因此这些捕获组是空的。因此,所有不是数字或点的字符都被替换为空字符串。

  • 第二部分 (\.)\D*(\d?)\D*(\d?).* 稍微复杂一些。它包含了三个捕获组:

    1. (\.) - 一个普通的 . 字符。
    2. (\d?) - 一个可选的数字。
    3. (\d?) - 另一个可选的数字。

    在这些捕获组之间的其余部分是用于匹配非数字字符的。此外,末尾的 .* 匹配在找到第一个点字符后剩余的内容,因此只进行一次替换,并使用剩余的整个输入内容。

请查看以下的测试 PHP 脚本:

<?php
$cases = array();
$cases['*$234.345'] = '234.34';
$cases['(9.9)'] = '9.9';
$cases['$34.455r.4r45,45.45'] = '34.45';
$cases['2023-05-29 03:40:11Z, License: CC BY-SA 4.0'] = '202305290340114.0';
$cases['9.95,6.432,0.3'] = '9.95';
$cases['po2iaw5e.ro1i7im8jjks;fl32;i.u12ma'] = '25.17';
$cases['oias25.spkks'] = '25.';
$cases['4545'] = '4545';
$cases['oi.as2.5.6spkks'] = '.25';
$cases['oi.as..spkks'] = '.';

$regex = '~[^\d.]+|(\.)\D*(\d?)\D*(\d?).*';
$replacement = '$1$2$3';
foreach ($cases as $input => $expected)
{
    $result = preg_replace($regex, $replacement, $input);
    $correct = $result == $expected;
    echo "Input: ".$input.", result: ".$result.", as expected: ".($correct ? 'true' : 'FALSE')."\n"."<br>";
    if (!$correct)
    {
        echo "\tShould be: ".$expected."\n";
    }
}

这将生成以下输出:

Input: *$234.345, result: 234.34, as expected: true
Input: (9.9), result: 9.9, as expected: true
Input: $34.455r.4r45,45.45, result: 34.45, as expected: true
Input: 2023-05-29 03:40:11Z, License: CC BY-SA 4.0, result: 202305290340114.0, as expected: true
Input: 9.95,6.432,0.3, result: 9.95, as expected: true
Input: po2iaw5e.ro1i7im8jjks;fl32;i.u12ma, result: 25.17, as expected: true
Input: oias25.spkks, result: 25., as expected: true
Input: 4545, result: 4545, as expected: true
Input: oi.as2.5.6spkks, result: .25, as expected: true
Input: oi.as..spkks, result: ., as expected: true
英文:

You can use the following preg_replace() call to replace the input with the number you are looking for:

<!-- language: php -->
preg_replace('~[^\d.]+|(.)\D*(\d?)\D*(\d?).*~', '$1$2$3', $input_string);

The regex replacement works as follow:

  • The first part [^\d.]+ is trivial and deletes everything that is not a digit or a dot with the captured groups &#39;$1$2$3&#39;. But since you are not catching anything in that part of the regex, these capture groups are empty. So every character that is not a digit or a dot get replaced with an empty string.

  • The second part (\.)\D*(\d?)\D*(\d?).* is a little bit more complicated. It has three capture groups:

    1. (\.) - An ordinary . character.
    2. (\d?) - An optional digit.
    3. (\d?) - Another optional digit.

    The remaining parts between these capture groups are for characters, which are not digits. Also the .* at the end matches the remaining of the content when you found your first dot character, so you do this replacement only once and with the whole remaining input.

Check the following test PHP script:

&lt;?php
$cases = array();
$cases[&#39;*$234.345&#39;] = &#39;234.34&#39;;
$cases[&#39;(9.9)&#39;] = &#39;9.9&#39;;
$cases[&#39;$34.455r.4r45,45.45&#39;] = &#39;34.45&#39;;
$cases[&#39;2023-05-29 03:40:11Z, License: CC BY-SA 4.0&#39;] = &#39;202305290340114.0&#39;;
$cases[&#39;9.95,6.432,0.3&#39;] = &#39;9.95&#39;;
$cases[&#39;po2iaw5e.ro1i7im8jjks;fl32;i.u12ma&#39;] = &#39;25.17&#39;;
$cases[&#39;oias25.spkks&#39;] = &#39;25.&#39;;
$cases[&#39;4545&#39;] = &#39;4545&#39;;
$cases[&#39;oi.as2.5.6spkks&#39;] = &#39;.25&#39;;
$cases[&#39;oi.as..spkks&#39;] = &#39;.&#39;;

$regex = &#39;~[^\d.]+|(\.)\D*(\d?)\D*(\d?).*~&#39;;
$replacement = &#39;$1$2$3&#39;;
foreach ($cases as $input =&gt; $expected)
{
    $result = preg_replace($regex, $replacement, $input);
    $correct = $result == $expected;
    echo &quot;Input: &quot;.$input.&quot;, result: &quot;.$result.&quot;, as expected: &quot;.($correct ? &#39;true&#39; : &#39;FALSE&#39;).&quot;\n&quot;.&quot;&lt;br&gt;&quot;;
    if (!$correct)
    {
        echo &quot;\tShould be: &quot;.$expected.&quot;\n&quot;;
    }
}

This will generate the following output:

<!-- language: none -->
Input: *$234.345, result: 234.34, as expected: true
Input: (9.9), result: 9.9, as expected: true
Input: $34.455r.4r45,45.45, result: 34.45, as expected: true
Input: 2023-05-29 03:40:11Z, License: CC BY-SA 4.0, result: 202305290340114.0, as expected: true
Input: 9.95,6.432,0.3, result: 9.95, as expected: true
Input: po2iaw5e.ro1i7im8jjks;fl32;i.u12ma, result: 25.17, as expected: true
Input: oias25.spkks, result: 25., as expected: true
Input: 4545, result: 4545, as expected: true
Input: oi.as2.5.6spkks, result: .25, as expected: true
Input: oi.as..spkks, result: ., as expected: true

huangapple
  • 本文由 发表于 2023年5月25日 10:40:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76328564.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定