正则表达式:匹配字符串中最后一个点号

68

我有一个文件名,其中可能有多个点,并且可以以任何扩展名结尾:

tro.lo.lo.lo.lo.lo.png

我需要使用正则表达式将最后一个句点替换为另一个字符串,例如@2x,然后再加上一个点(非常类似于视网膜图像文件名),即:

tro.lo.png -> tro.lo@2x.png

这是我目前的代码,但它无法匹配任何内容...

str = "http://example.com/image.png";
str.replace(/.([^.]*)$/, " @2x.");

有任何建议吗?


如果你想用正则表达式来实现它,你需要一个负向先行断言,但你真的不应该这样做。 - Benjamin Gruenbaum
9个回答

118

不需要使用正则表达式。可以使用String.lastIndexOf

var str = 'tro.lo.lo.lo.lo.lo.zip';
var i = str.lastIndexOf('.');
if (i != -1) {
    str = str.substr(0, i) + "@2x" + str.substr(i);
}

点击查看实际效果.

更新: 一个正则表达式的解决方案,只是为了好玩:

str = str.replace(/\.(?=[^.]*$)/, "@2x.");

匹配一个字面点号,然后断言((?=)正向先行断言)在字符串结束之前没有其他字符是点号。替换文本应该包括被匹配的那个点号,除非你想要删除它。


我该如何使用那个整数来进行.replace()操作? - alt
很棒的答案!为什么这比正则表达式更好/更有效/代码更少? - alt
3
@JacksonGariety。这篇文章更易读,速度稍快。 - gdoron
嗨,对于正则表达式专家,我有一个新的快速问题... 我应该如何最好地删除url开头的'('和结尾的')',而不会将它们从字符串的其他位置中删除?谢谢。 - alt
你需要匹配 "url\((-url-regex-here-)\)" 并替换为 "$1",这样就只剩下 URL 了。-url-regex-here- 是一个匹配 URL 的正则表达式;你可以在 Google 上搜索它,或者使用 [^)]+ 这个快速而不太精确的解决方案。 - Jon
显示剩余3条评论

32

只需在替换字符串中使用特殊替换模式$1

console.log("tro.lo.lo.lo.lo.lo.png".replace(/\.([^.]+)$/, "@2x.$1"));
// "tro.lo.lo.lo.lo.lo@2x.png"


2
正确回答了问题提出者的问题。 - Qtax
2
@Qtax:不完全正确,因为如果最后一个点也是最后一个字符,它将无法工作。 - Jon
@Jon,没错。几乎正确了。;) 但是/\.([^.]*)$/就可以了,不需要使用lookaround。 - Qtax
1
我不确定文件名是否可以以 . 作为最后一个字符。 - Salman A

6
你可以使用表达式\.([^.]*?)
str.replace(/\.([^.]*?)$/, "@2x.$1");

您需要引用$1子组来将该部分复制回结果字符串中。

我认为这个需要在"$1@2x"的末尾再加一个句号才能正常工作,对吗? - alt
有点匆忙地回答了那个问题 - 现在已经修复了,以便更符合您原来的正则表达式。 - user193476
我认为您在替换字符串中漏掉了一个 .。我更喜欢转义 .,但字符类可能更易于阅读。.replace(/(.*)\./, "$1@2x.")。无论如何,使用 * 量词的贪婪属性提供了简单的解决方案,+1。 - nhahtdh

5

工作演示 http://jsfiddle.net/AbDyh/1/

代码

var str = 'tro.lo.lo.lo.lo.lo.zip',
    replacement = '@2x.';
str = str.replace(/.([^.]*)$/, replacement + '$1');

$('.test').html(str);

alert(str);​

1
不太对,输出缺少一个点。 - gdoron
1
你的输出应该是 tro.lo.lo.lo.lo.lo@2xzip - gdoron
@gdoron 哈哈,只差了35秒 :) 干杯!这里有更新版本 http://jsfiddle.net/AbDyh/1/ - Tats_innit
@gdoron 你太棒了 - 顺便说一下,我在想你什么时候会申请成为版主啊!不管怎样,SO并不是聊天应用程序,只是一个建议! - Tats_innit
不会很快...我不想要这份工作,也没有时间。祝好。:) - gdoron
@gdoron 如果你改变主意了,你将得到我的++1推荐和最好的评论! :) - Tats_innit

3

要匹配字符串开头到(包括)最后一个字符的所有字符,请使用:

^.*\.(?=[^.]*$)  To match the last occurrence of the "." character

^.*_(?=[^.]*$)   To match the last occurrence of the "_" character

2
使用\.匹配一个句点。字符.匹配任何字符。
因此,str.replace(/\.([^\.]*)$/, ' @2x.')

1
尝试你的代码:"tro.lo.lo.lo.lo.lo.zip".replace(/\.([^\.]*)$/, ' @2x.')。它不起作用。对不起。 - gdoron
很酷,我不知道正则表达式还有这个用法。 - alt

1
'tro.lo.lo.lo.lo.lo.png'.replace(/([^\.]+).+(\.[^.]+)/, "$1.@x2$2")

这个答案缺少了它的教育解释。 - undefined

1
您可以简单地像这样做:

> "tro.lo.lo.lo.lo.lo.zip".replace(/^(.*)\./, "$1@2x");
'tro.lo.lo.lo.lo.lo@2xzip'

这个答案缺少了教育性的解释。 - undefined

1
为什么不简单地分割字符串并将后缀添加到倒数第二个条目:
var arr = 'tro.lo.lo.lo.lo.lo.zip'.split('.');
arr[arr.length-2] += '@2x';
var newString = arr.join('.');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接