V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
firhome
V2EX  ›  程序员

数字输入转换的正则表达式...帮忙看看这个能一次匹配吗?

  •  
  •   firhome · 2014-02-18 10:20:54 +08:00 · 3755 次点击
    这是一个创建于 3966 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有字符串 '--.3.--.---3'

    前面有N个 -- 的时候 只保留一个

    有点的时候保留距离数字最近的点

    '--.3.--.---3' 转换 -.33

    '-.-3.---.--5---.' 转换 -3.5
    16 条回复    1970-01-01 08:00:00 +08:00
    iptux
        1
    iptux  
       2014-02-18 12:19:48 +08:00
    留个爪,想看答案
    znx5858
        2
    znx5858  
       2014-02-18 13:52:12 +08:00   ❤️ 1
    没领会到gist。“前面有N个 -- 的时候 只保留一个”,中间的“-”需要全部去掉么?
    vibbow
        3
    vibbow  
       2014-02-18 14:02:46 +08:00   ❤️ 1
    '--.3.--.---3' 转换 -.33
    为什么结果不是 -3.3 或者 -.3.3
    ianva
        4
    ianva  
       2014-02-18 14:17:59 +08:00   ❤️ 1
    s/^\(-\)*\(\.\)*-*\([0-9][0-9]*\)/\1\2\3/
    /^-*\./b hasPreDot
    s/^\(-*[0-9][0-9]*\)\(-*\(\.\)*-*\)*/\1\3/
    s/\([0-9][0-9]*\)\(--*\.*-*\)/\1/g
    t
    :hasPreDot
    s/\([0-9][0-9]*\)\(-*\.*-*\)*/\1/g
    gongweixin
        5
    gongweixin  
       2014-02-18 16:36:27 +08:00   ❤️ 1
    我也没理解楼主的意思,“前面有N个 -- 的时候 只保留一个” 保留哪个?“有点的时候保留距离数字最近的点” 离那个数字最近的??'--.3.--.---3' 转换 -.33 为什么'-.-3.---.--5---.' 转换 不是-.35 ?
    gongweixin
        6
    gongweixin  
       2014-02-18 16:37:45 +08:00   ❤️ 1
    .3--.5 结果是什么呢? -3.--5 结果是什么呢? 楼主说的不清楚啊。
    firhome
        7
    firhome  
    OP
       2014-02-18 16:46:15 +08:00
    我整理一下.(我题目里第二个有误)

    "如果有负号一定在数字前面,小数点在负号之后(不挨着也可以.) 其余多余的负号都删除掉"

    也就是说:

    .--.3...5 >>> -.35
    ----3...5 >>> -3.5

    --.--3.---5 >>> -.35

    ......3.5 >>> .35

    3....---...5--- >>> 3.5

    为啥可以 -.35 或者 .35 因为js的parseFloat结果是 -0.35 和 0.35
    xierch
        8
    xierch  
       2014-02-18 22:07:31 +08:00
    必须要正则?
    还是写几个 if 吧..
    xierch
        9
    xierch  
       2014-02-18 22:44:28 +08:00
    jakwings
        10
    jakwings  
       2014-02-19 01:46:01 +08:00   ❤️ 1
    真是奇葩的问题。也不说会出现多少段数字。那我默认最多两段。
    要匹配不难,要转换的话肯定得接着用 if 判断一下吧。
    那我用 Javascript 那弱弱的正则表达式来匹配:/^([.\-]*\d+)+[.\-]*$/

    接着可用另一个 Javascript 语句来转换(最多匹配转换两段数字):
    str.replace(/^(?:\.*(-))?[.\-]*?(\.\d+|\d+\.)(?:[.\-]+(\d+)[.\-]*)?$/, '$1$2$3');
    jakwings
        11
    jakwings  
       2014-02-19 01:47:20 +08:00   ❤️ 1
    @jakwings 转换语句更正一下:
    str.replace(/^(?:\.*(-))?[.\-]*?(\.\d+|\d+\.)(?:[.\-]+(\d+))?[.\-]*$/, '$1$2$3')
    jakwings
        12
    jakwings  
       2014-02-19 01:50:46 +08:00   ❤️ 1
    @jakwings 再更正一下:
    str.replace(/^(?:\.*(-))?[.\-]*?(\.\d+|\d+\.|\d+)(?:[.\-]+(\d+))?[.\-]*$/, '$1$2$3');
    jakwings
        13
    jakwings  
       2014-02-19 05:33:47 +08:00   ❤️ 1
    @jakwings 回来回味了一下楼主的题目,发现我还是理解错了?

    最前面有负号则转换出负数,前方(负号后)*任意位置*有点就加上小数点并忽略后面任意位置的点,若前方没有点而后方(数字之前)*任意位置*有点则在后方加上小数点。好吧,我再更正一下转换语句:

    str.replace(/^\.*(-)?(?:-*(\.)[.\-]*(\d+)(?:[.\-]*(\d+))?|[.\-]*(\d+)(?:-*(\.)?[.\-]*(\d+))?)[.\-]*$/, '$1$2$3$4$5$6$7');

    详细解释如下(非 [] 中的空格请忽略):
    @^
    \.*(-)? #检测开头的负号,并且忽略负号前的点
    (?: #进入多种模式匹配
    -*(\.)[.\-]* #找到(负号后的)点
    (\d+)(?:[.\-]*(\d+))? #找到小数点后的数字,并忽略其后的点
    | #第二个模式开始
    [.\-]*(\d+) #找到(小数点前的)数字
    (?:-*(\.)?[.\-]*(\d+))? #找到(小数点及其后的)其余数字
    ) #匹配模式结束
    [.\-]* #忽略其后所有无意义字串
    @$

    当然,我不知道会不会出现这样的字串「3---5」,上面会将其转换为「35」。
    jakwings
        14
    jakwings  
       2014-02-19 07:39:08 +08:00   ❤️ 1
    @jakwings 再次修正,关于忽略最负号前的点的:
    str.replace(/^(?:\.*(-))?(?:-*(\.)[.\-]*(\d+)(?:[.\-]*(\d+))?|[.\-]*(\d+)(?:-*(\.)?[.\-]*(\d+))?)[.\-]*$/, '$1$2$3$4$5$6$7');

    顺便,这个正则表达式也不算怎么高效。还不如先简单配置再通过多次替换来转换:
    http://cxg.de/_7d95ff.htm
    ianva
        15
    ianva  
       2014-02-19 10:56:55 +08:00
    我觉得这个还是写个parser靠谱,sed 可以实现条件分支但也太麻烦了,没可读性,一个正则解决基本是没有可读性,各种错误是少不了的
    jakwings
        16
    jakwings  
       2014-02-19 11:24:00 +08:00
    =_= 楼主真厚道啊,给我的每条回复送了感谢(铜币)。今天被送感谢 V2EX 貌似没有提醒(难道频繁送同一人感谢会被当骚扰取消通知?)……
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2622 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 05:16 · PVG 13:16 · LAX 21:16 · JFK 00:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.