Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用正则表达式选择千位分隔符字符_Php_Regex_Localization_Numbers - Fatal编程技术网

Php 使用正则表达式选择千位分隔符字符

Php 使用正则表达式选择千位分隔符字符,php,regex,localization,numbers,Php,Regex,Localization,Numbers,我需要更改给定字符串中包含数字的小数分隔符 什么正则表达式代码只能选择字符串中的千位分隔符 当周围有数字时,只需选择。例如,仅当123456我需要选择并替换, 我正在把英语数字转换成波斯语(例如:Hello 123变成Hello۱۲۳)。现在我也需要用波斯语版本替换十进制分隔符。但我不知道如何用正则表达式选择它。e、 g.Hello 121534大多数人成为Hello۱۱۱۱/۵۳۴ 需要替换的字符是,为/,在PHP中,您可以使用 这将返回:Hello 123X456您可以编写一个正则表达式,用

我需要更改给定字符串中包含数字的小数分隔符

什么正则表达式代码只能选择字符串中的千位分隔符

当周围有数字时,只需选择。例如,仅当
123456
我需要选择并替换

我正在把英语数字转换成波斯语(例如:
Hello 123
变成
Hello۱۲۳
)。现在我也需要用波斯语版本替换十进制分隔符。但我不知道如何用正则表达式选择它。e、 g.
Hello 121534
大多数人成为
Hello۱۱۱۱/۵۳۴


需要替换的字符是
/

,在PHP中,您可以使用


这将返回:Hello 123X456

您可以编写一个正则表达式,用千位分隔符捕获数字,然后用所需的分隔符聚合两个数字部分:

$text = "Hello, world, 121,534" ;
$pattern = "/([0-9]{1,3}),([0-9]{3})/" ;
$new_text = preg_replace($pattern, "$1X$2", $text); // replace comma per 'X', keep other groups intact.

echo $new_text ; // Hello, world, 121X534

将正则表达式与lookarounds一起使用

$new_string = preg_replace('/(?<=\d),(?=\d)/', '/', $string);

根据你的问题,你面临的主要问题是把英文数字转换成波斯语

在PHP中,有一个库可以根据区域设置对数字进行格式化和解析,您可以在类NumberFormatter中找到它,该类利用Unicode公共区域设置数据存储库(CLDR)最终处理世界上已知的所有语言

因此,将数字
123456
en_-UK
(或
en_-US
)转换为
fa_-IR
,如下示例所示:

$string = '123,456';
$float = (new NumberFormatter('en_UK', NumberFormatter::DECIMAL))->parse($string);
var_dump(
    (new NumberFormatter('fa_IR', NumberFormatter::DECIMAL))->format($float)
);
输出:

string(14) "۱۲۳٬۴۵۶"
it need to only select , when there is number around it. for example only 
when < 123,456 (123456.0000) = ۱۲۳٬۴۵۶ > i need to select and replace "," I'm converting English
numbers into Persian (e.g: "Hello < 123 (123.0000) = ۱۲۳ >" becomes "Hello ۱۲۳"). now I need to
replace the Decimal separator with Persian version too. but I don't know how
I can select it with regex. e.g: "Hello < 121,534 (121534.0000) = ۱۲۱٬۵۳۴ >" most become 
"Hello ۱۲۱/۵۳۴" The character that needs to be replaced is , with /
()

现在这表明(不知怎么的)如何转换数字。我对波斯语不太在行,所以如果我在这里使用了错误的区域设置,请原谅。可能还有一些选项可以告诉您使用哪个字符进行分组,但就目前的示例而言,这只是为了表明数字的转换是由现有库负责的。您不需要重新发明它,因为甚至是一种误用的措辞,这不是一个人能做的,或者至少单独做这件事有点疯狂

因此,在澄清了如何转换这些数字之后,问题仍然是如何在整个文本中进行转换。那么,为什么不找到所有可能查找的位置,然后尝试解析匹配,如果成功(并且只有成功),将其转换为不同的区域设置呢

幸运的是,如果解析失败,该方法将返回false(如果您对更多细节感兴趣,将有更多错误报告),因此这是可行的

对于正则表达式匹配,它只需要一个与数字匹配的模式(最大匹配获胜),并且可以通过回调进行替换。在以下示例中,转换是详细的,因此实际的解析和格式设置更为明显:

# some text
$buffer = <<<TEXT
it need to only select , when there is number around it. for example only 
when 123,456 i need to select and replace "," I'm converting English
numbers into Persian (e.g: "Hello 123" becomes "Hello ۱۲۳"). now I need to
replace the Decimal separator with Persian version too. but I don't know how
I can select it with regex. e.g: "Hello 121,534" most become 
"Hello ۱۲۱/۵۳۴" The character that needs to be replaced is , with /
TEXT;    

# prepare formatters
$inFormat = new NumberFormatter('en_UK', NumberFormatter::DECIMAL);
$outFormat = new NumberFormatter('fa_IR', NumberFormatter::DECIMAL);

$bufferWithFarsiNumbers = preg_replace_callback(
    '(\b[1-9]\d{0,2}(?:[ ,.]\d{3})*\b)u',
    function (array $matches) use ($inFormat, $outFormat) {
        [$number] = $matches;

        $result = $inFormat->parse($number);
        if (false === $result) {
            return $number;
        }

        return sprintf("< %s (%.4f) = %s >", $number, $result, $outFormat->format($result));
    },
    $buffer
);

echo $bufferWithFarsiNumbers;
()

编辑:

要仅在数千个块上匹配同一分组字符,可以创建命名引用并将其引用回以进行重复:

(\b[1-9]\d{0,2}(?:(?<grouping_char>[ ,.])\d{3}(?:(?&grouping_char)\d{3})*)?\b)u
(\b[1-9]\d{0,2}(?:(?[,。])\d{3}(?:(?&分组字符)\d{3})*)?\b)u
(现在这本书不那么容易读了,)

要最终确定答案,只需将return子句压缩为
return$outFormat->format($result);
,而
$outFormat
NumberFormatter可能需要更多的配置,但由于它在闭包中可用,因此可以在创建它时完成

()


我希望这是有帮助的,并打开了一个更广阔的图景,不要仅仅因为碰壁(而且只在那里)而寻找解决方案.Regex本身通常不是答案。我很确定有些Regex怪胎可以给你一个非常稳定的一行代码,但是使用它的环境不会非常稳定。但是,不要说只有一个答案。而是将不同层次的行为结合在一起(分而治之)允许依赖稳定的数字转换,即使仍然不确定如何对英文数字进行正则表达式模式转换。

使用空格和点也可以用作千位分隔符,带十进制(阿拉伯语)数字(我的措辞可能不是100%正确,只是反映了我的理解)。我会按照巴尔马的建议去做,但是,向前看或向后看必须是固定长度的(两个中的一个)。别忘了。@hakre向后看和向前看应该是
\d
为了匹配一个数字,不需要量词。@Barmar:一千个分隔符有
[1-9]\d{,2}
后面和
[1-9]\d{2}后面是动态长度,前面是固定的。没有检查这个组合是否可以。这将替换所有逗号,而不仅仅是用作千个分隔符的逗号。考虑<代码>嗨,数字是123456 < /代码>它将变成<代码> HiX。号码是123x466< /代码>如果有两个逗号,则不起作用。数字中有,如123456789。与昵称不匹配:“Hi Barmar447123天前,你开始在我们的新平台上做正确的事情”…如果我能听你的评论的话下面,你会认为值得投反对票,对吗?逗号后面应该有空格。啊,这不是问题中写的,让我猜猜,只是说答案合适,对吗?这只是普通的排版,你在句子中逗号后面加空格。嗯,普通的排版(没有错误,永远不会)比如说,你的幸运日花了444,22欧元。
你一定是说。我很确定你会在自己的文章旁边马上否认这种正常的排版。从你的回答来看,这是不正常的,对吧?
                    pattern for Unicode UTF-8 strings
                                 |
(\b[1-9]\d{0,2}(?:[ ,.]\d{3})*\b)u
  |                 |          |
  |        grouping character  |
  |                            |
word boundary -----------------+
(\b[1-9]\d{0,2}(?:(?<grouping_char>[ ,.])\d{3}(?:(?&grouping_char)\d{3})*)?\b)u