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

2014-02-18 10:20:54 +08:00
 firhome
有字符串 '--.3.--.---3'

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

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

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

'-.-3.---.--5---.' 转换 -3.5
3578 次点击
所在节点    程序员
16 条回复
iptux
2014-02-18 12:19:48 +08:00
留个爪,想看答案
znx5858
2014-02-18 13:52:12 +08:00
没领会到gist。“前面有N个 -- 的时候 只保留一个”,中间的“-”需要全部去掉么?
vibbow
2014-02-18 14:02:46 +08:00
'--.3.--.---3' 转换 -.33
为什么结果不是 -3.3 或者 -.3.3
ianva
2014-02-18 14:17:59 +08:00
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
2014-02-18 16:36:27 +08:00
我也没理解楼主的意思,“前面有N个 -- 的时候 只保留一个” 保留哪个?“有点的时候保留距离数字最近的点” 离那个数字最近的??'--.3.--.---3' 转换 -.33 为什么'-.-3.---.--5---.' 转换 不是-.35 ?
gongweixin
2014-02-18 16:37:45 +08:00
.3--.5 结果是什么呢? -3.--5 结果是什么呢? 楼主说的不清楚啊。
firhome
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
2014-02-18 22:07:31 +08:00
必须要正则?
还是写几个 if 吧..
xierch
2014-02-18 22:44:28 +08:00
jakwings
2014-02-19 01:46:01 +08:00
真是奇葩的问题。也不说会出现多少段数字。那我默认最多两段。
要匹配不难,要转换的话肯定得接着用 if 判断一下吧。
那我用 Javascript 那弱弱的正则表达式来匹配:/^([.\-]*\d+)+[.\-]*$/

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

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

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

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

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

顺便,这个正则表达式也不算怎么高效。还不如先简单配置再通过多次替换来转换:
http://cxg.de/_7d95ff.htm
ianva
2014-02-19 10:56:55 +08:00
我觉得这个还是写个parser靠谱,sed 可以实现条件分支但也太麻烦了,没可读性,一个正则解决基本是没有可读性,各种错误是少不了的
jakwings
2014-02-19 11:24:00 +08:00
=_= 楼主真厚道啊,给我的每条回复送了感谢(铜币)。今天被送感谢 V2EX 貌似没有提醒(难道频繁送同一人感谢会被当骚扰取消通知?)……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/100691

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX