Chinaunix

标题: 出道正则难题,数字千分点 [打印本页]

作者: 黑色阳光_cu    时间: 2011-03-11 15:18
标题: 出道正则难题,数字千分点
本帖最后由 黑色阳光_cu 于 2011-03-11 15:19 编辑
  1. my $v = "12321347317347317.12734712347313471324";
  2. $v =~ s/.../.../;
  3. print $v;
复制代码
请写一句正则,把 $v 变成 12,321,347,317,347,317.127,347,123,473,134,713,24 。也就是说,按千分点把数字隔开,注意小数部分是从左到右每3位一组,和整数部分刚好相反。
要求一句正则 s/.../.../ 搞定,不准用 /e 修饰;另外,不管有没有小数部分,不管整数部分和小数部分有几位数字,答案都要正确。
作者: zhlong8    时间: 2011-03-11 16:39
while ($v =~ s/\d\K(?=\d{3},)|
    ,\d{3}\K(?=\d)|
    \d\K(?=\d{3}\.)|
    \.\d{3}\K(?=\d)|
    \d\K(?=\d{3}$)/,/x) {
    say $v;
}
这样递归思想应该最简单吧,不会一句 s/// 搞定 :mrgreen:
作者: blackold    时间: 2011-03-11 16:49
本帖最后由 blackold 于 2011-03-11 17:19 编辑

回复 1# 黑色阳光_cu


  1 while $v =~ s/(^-?\d+)\K(\d\d\d)|(\..*?\d\d\d)\K(\d)/,$&/;

这个算不算一句s?
作者: iLRainyday    时间: 2011-03-11 18:46
本帖最后由 iLRainyday 于 2011-03-11 19:06 编辑
  1. s/(?=(\d\d\d)+\.)|(?<=\.(\d\d\d)+)/,/g;
复制代码
可惜perl不支持任意深度的逆序环视,所以在regexbuddy中,只能够使用.NET或者是JGsoft的regex引擎测试通过。
作者: 黑色阳光_cu    时间: 2011-03-11 18:55

  1. my $v = "12321347317347317.12734712347313471324";
  2. $v =~ s/\G(?:(?!^\d+$)(?!\d*\.)\d{3}(?!$)\K|\d{0,3}\.\d{3}(?!$)\K|\d*?\K(?!^)(?=(?:\d{3})+(?:\.|$)))/,/g;
  3. warn $v;
复制代码
加 /x 清淅点:
  1. my $v = "12321347317347317.12734712347313471324";
  2. $v =~ s/
  3. \G
  4. (?:
  5.         (?!^\d+$)(?!\d*\.)\d{3}(?!$)\K
  6.         |
  7.         \d{0,3}\.\d{3}(?!$)\K
  8.         |
  9.         \d*?\K(?!^)(?=(?:\d{3})+(?:\.|$))
  10. )
  11. /,/xg;
  12. warn $v;
复制代码

作者: 黑色阳光_cu    时间: 2011-03-12 13:09

作者: yinyuemi    时间: 2011-03-12 14:33
本帖最后由 yinyuemi 于 2011-03-12 16:34 编辑

perl还在学,用sed凑凑热闹,呵呵

echo "12321347317347317.12734712347313471324" |sed -r ':a;s/([^,\|\.]{3})([^,\|\.]*$)/\1,\2/;s/^([^,\|\.]*)([^,\|\.]{3})/\1,\2/;ta'
12,321,347,317,347,317.127,347,123,473,134,713,24

perl写得很挫啊,

my $v = "12321347317347317.12734712347313471324";

while ($v =~ /[^,|\.]{3}[^\.|,]*$/)
{$v =~ s/([^,|\.]{3})([^\.|,]*$)/$1,$2/;
while ( $v =~ /^[^,|\.]*[^,|\.]{3}/)
{$v =~ s/(^[^,|\.]*)([^,|\.]{3})/$1,$2/;}
}

print $v;
作者: CrkED    时间: 2011-03-13 05:18
回复 1# 黑色阳光_cu

1 while $v=~s/(\.(?:\d{3})+)(\d+?)/$1,$2/ or $v=~s/(\d+)((?:\d{3})+?)/$1,$2/;
作者: wdavid    时间: 2011-03-13 10:29
回复  黑色阳光_cu

1 while $v=~s/(\.(?:\d{3})+)(\d+?)/$1,$2/ or $v=~s/(\d+)((?:\d{3})+?)/$1,$2/;
CrkED 发表于 2011-03-13 05:18


可以放在一个s///里。
  1. 1 while $v=~s/(?|
  2. (\.(?:\d{3})+)(\d+?)
  3. |
  4. (\d+)((?:\d{3})+?))
  5. /$1,$2/x
复制代码

作者: liyangole    时间: 2011-03-13 21:04
回复 5# 黑色阳光_cu


    \K什么意思,use perl什么版本了
作者: lkk2003rty    时间: 2011-03-14 01:53
回复 10# liyangole


     \K         Keep the stuff left of the \K, don't include it in $&
作者: 珞水的大叔    时间: 2011-03-14 12:51
我也单行一下
  1. my $v = "12321347317347317.12734712347313471324";
  2. $v =~ s/(?<=\d)(?=(\d\d\d)+\.)|(?<=\.\d\d\d)(?!$)|(?<=\G\d\d\d)(?!\.|$)/,/g;print $v;
复制代码
也x一个,呵呵
  1. my $v = "12321347317347317.12734712347313471324";
  2. $v =~ s/(?<=\d)(?=(\d\d\d)+\.)    #处理整数部分
  3.         |
  4.         (?<=\.\d\d\d)(?!$)        #处理小数点后面第一次千分位,例子中就是.127后面的逗号
  5.         |
  6.         (?<=\G\d\d\d)(?!\.|$)     #处理小数点后第一个千分位以后的内容
  7.         /,/gx;
  8. print $v;
复制代码

作者: 黑色阳光_cu    时间: 2011-03-14 13:25
我也单行一下也x一个,呵呵
珞水的大叔 发表于 2011-03-14 12:51


你试试 my $v = "12321347317347317";
作者: isaacblue    时间: 2011-03-14 15:12
while(($v=~s/(\d{1,})(\d{3})([\._])/\1_\2\3/)||($v=~s/([\._])(\d{3})(\d{1,})/\1\2_\3/)||($v=~s/(\d{1,})(\d{3})$/\1_\2/)){}
这样也算一句话吧。。。。。。
作者: 珞水的大叔    时间: 2011-03-14 17:30
回复 13# 黑色阳光_cu


    那就这样,呵呵
  1. $v = "12321347317347317";
  2. $v =~ s/(?<=^\d)(?=(\d\d\d)+$)     #处理不含小数点的情况
  3.         |
  4.         (?<=^\d\d)(?=(\d\d\d)+$)   #处理不含小数点的情况
  5.         |
  6.         (?<=\d)(?=(\d\d\d)+\.)    #处理整数部分
  7.         |
  8.         (?<=\.\d\d\d)(?!$)        #处理小数点后面第一次千分位,例子中就是.127后面的逗号
  9.         |
  10.         (?<=\G\d\d\d)(?!\.|$)     #处理小数点后第一个千分位以后的内容,或者不含小数点的情况
  11.         /,/gx;
  12. print $v;
复制代码

作者: 黑色阳光_cu    时间: 2011-03-15 10:03
回复  黑色阳光_cu


    那就这样,呵呵
珞水的大叔 发表于 2011-03-14 17:30



   
这次对了
作者: py    时间: 2011-03-15 10:54
请写一句正则,把 $v 变成 12,321,347,317,347,317.127,347,123,473,134,713,24 。也就是说,按千分点把数字 ...
黑色阳光_cu 发表于 2011-03-11 15:18


这是《Mastering Regular Expressions, 2nd Edition》在讲lookbehind和lookahead的时候使用的例子。详见英文版的2.3.5.4章
  1. ~ s/(?<=\d)(?=(\d\d\d)+(?!\d))/,/g
复制代码

作者: iLRainyday    时间: 2011-03-15 11:35
这是《Mastering Regular Expressions, 2nd Edition》在讲lookbehind和lookahead的时候使用的例子。详见 ...
py 发表于 2011-03-15 10:54


你没看明白需求。这个regex只能拿来处理小数点之前的部分。因为perl不支持任意深度的lookbehind,所以最恶心的是如何处理小数点之后的部分。如果可以分开写,当然好处理,MRE上也给的有例子,使用$1,进行全局替换就行了。
作者: 珞水的大叔    时间: 2011-03-15 12:38
回复 16# 黑色阳光_cu


    顺便请教一下, \K 究竟用来作什么,它不把左边的内容存到$&里面是为了提高效率么?
作者: pangeno    时间: 2011-03-17 22:59
回复 4# iLRainyday


    弱弱地问一句:?=   和  ?<=  是什么意思?
作者: 珞水的大叔    时间: 2011-03-18 10:15
回复 20# pangeno


    (?=)是顺序环视,如:    $lala =~ m/a(?=b)/   表示查找后面有b的a
   (?<=)是逆序环视,如:  $lala =~ m/(?<=b)a/ 表示查找前面有b的a
作者: pangeno    时间: 2011-03-18 16:10
回复 21# 珞水的大叔


    谢啦
作者: xiaoxinlovernes    时间: 2011-08-24 10:59
本帖最后由 zhlong8 于 2011-08-24 11:05 编辑

1. my $v = "12321347317347317.12734712347313471324";
   2. $v =~ s/\G(?:(?!^\d+$)(?!\d*\.)\d{3}(?!$)\K|\d{0,3}\.\d{3}(?!$)\K|\d*?\K(?!^)(?=(?:\d{3})+(?:\.|$)))/,/g;
   3. warn $v;
莫言(63359149)  10:43:13
my $v = "12321347317347317.12734712347313471324";
$v =~ s/\G(?:(?!^\d+$)(?!\d*\.)\d{3}(?!$)\K|\d{0,3}\.\d{3}(?!$)\K|\d*?\K(?!^)(?=(?:\d{3})+(?:\.|$)))/,/g;
warn $v;




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2