如何替换字符串中所有但第一次出现的模式
Posted
技术标签:
【中文标题】如何替换字符串中所有但第一次出现的模式【英文标题】:How to replace all BUT the first occurrence of a pattern in string 【发布时间】:2011-12-19 02:04:40 【问题描述】:快速问题:我的模式是一个 svg 字符串,它看起来像 l 5 0 l 0 10 l -5 0 l 0 -10
要与参考进行一些单元测试比较,我需要抛弃除第一个 l
之外的所有内容,我知道我可以将它们全部抛弃并放一个 'l ' 提前,或者我可以使用子字符串。但我想知道这是否有一个 javascript 正则表达式成语?
【问题讨论】:
第一个 l 总是在字符串的开头吗? 我知道你说过你不想要这个,但是直到第一个空格的子字符串似乎最容易阅读和维护。 @Mark 是这个用例,它甚至是“l”,但这也适用于负前瞻。 @Randy 是的,我知道,但我想加深对正则表达式的了解。您关于可读性和可维护性的观点值得考虑。我将从评论开始。 【参考方案1】:您可以尝试否定前瞻,避免字符串的开头:
/(?!^)l/g
看是否在线:jsfiddle
【讨论】:
我正在尝试修改它以适用于出现的第一个“-”字符,但我遇到了非常困难的时期:(。感谢任何帮助。提前致谢。 如何将它与变量一起使用? @GrantRobertSmith 我知道这已经很晚了,但我提供的答案涵盖了我认为您正在寻找的内容。 这仅在第一个l
也位于字符串开头时才有效。【参考方案2】:
除了第一个模式匹配之外,没有 JS RegExp 可以替换所有内容。但是,您可以通过将函数作为第二个参数传递给 replace
method 来实现此行为。
var regexp = /(foo bar )(red)/g; //Example
var string = "somethingfoo bar red foo bar red red pink foo bar red red";
var first = true;
//The arguments of the function are similar to $0 $1 $2 $3 etc
var fn_replaceBy = function(match, group1, group2) //group in accordance with RE
if (first)
first = false;
return match;
// Else, deal with RegExp, for example:
return group1 + group2.toUpperCase();
string = string.replace(regexp, fn_replaceBy);
//equals string = "something foo bar red foo bar RED red pink foo bar RED red"
函数 (fn_replaceBy
) 为每个匹配执行。在第一次匹配时,该函数立即返回匹配的字符串(没有任何反应),并设置一个标志。
每隔一个匹配项将根据函数中描述的逻辑进行替换:通常,您使用$0 $1 $2
等来引用组。在 fn_replaceBy
中,函数参数等于:第一个参数 = $0
,第二个参数 = $1
,等等。
匹配的子字符串将被函数fn_replaceBy
的返回值替换。使用函数作为replace
的第二个参数允许非常强大的应用程序,例如intelligent html parser。
另见:MDN: String.replace > Specifying a function as a parameter
【讨论】:
我不相信“智能 HTML 解析器”不会链接到“使用正则表达式解析 HTML”的答案,哈哈。但非常好的答案,这正是我所需要的。 :)【参考方案3】:这不是最漂亮的解决方案,但您可以用任意的东西(如占位符)替换第一次出现并用链替换来完成其余的逻辑:
'-98324792u4234jkdfhk.sj.dh-f01' // construct valid float
.replace(/[^\d\.-]/g, '') // first, remove all characters that aren't common
.replace(/(?!^)-/g, '') // replace negative characters that aren't in beginning
.replace('.', '%FD%') // replace first occurrence of decimal point (placeholder)
.replace(/\./g, '') // now replace all but first occurrence (refer to above)
.replace(/%FD%(0+)?$/, '') // remove placeholder if not necessary at end of string
.replace('%FD%', '.') // otherwise, replace placeholder with period
生产:
-983247924234.01
这只是扩展了任何人在寻找一个不能依赖于第一个匹配/出现是字符串中的第一个字符的示例的接受答案。
【讨论】:
【参考方案4】: "l 5 0 l 0 10 l -5 0 l 0 -10".replace(/^\s+/, '').replace(/\s+l/g, '')
确保第一个'l'
前面没有空格,并删除后面跟'l'
的任何空格。
【讨论】:
【参考方案5】:这样的?
"l 5 0 l 0 10 l -5 0 l 0 -10".replace(/[^^]l/g, '')
【讨论】:
虽然这在这种情况下确实有效,但^
不代表字符类中的文字字符吗?
[^^]
匹配除'^'
之外的任何字符。它在您需要的输入开头以外的任何点都不匹配零字符。 (!/[^^]/.test('^') && /[^^]/.test('x')) === true
【参考方案6】:
我在https://www.regextester.com/99881 找到了这个解决方案,使用了lookbehind 模式:
/(?<=(.*l.*))l/g
或者更一般的
/(?<=(.*MYSTRING.*))MYSTRING/g
其中MYSTRING
是您要删除的内容。
(顺便说一句,这也可能是一个有用的字符串,用于删除电子邮件主题字符串中除第一次出现的“Re:”之外的所有内容。)
【讨论】:
所有正则表达式风格不支持可变长度后视。在 Javascript 中,并非所有浏览器都支持lookbehind。以上是关于如何替换字符串中所有但第一次出现的模式的主要内容,如果未能解决你的问题,请参考以下文章