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