简体   繁体   中英

How to replace all BUT the first occurrence of a pattern in string

quick question: my pattern is an svg string and it looks like l 5 0 l 0 10 l -5 0 l 0 -10 To do some unittest comparison against a reference I need to ditch all but the first l I know i can ditch them all and put an 'l' upfront, or I can use substrings. But I'm wondering is there a javascript regexp idiom for this?

You can try a negative lookahead, avoiding the start of the string:

/(?!^)l/g

See if online: jsfiddle

There's no JS RegExp to replace everything-but-the-first-pattern-match. You can, however, implement this behaviour by passing a function as a second argument to the 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"

The function ( fn_replaceBy ) is executed for each match. At the first match, the function immediately returns with the matched string (nothing happens), and a flag is set.
Every other match will be replaced according to the logic as described in the function: Normally, you use $0 $1 $2 , et cetera, to refer back to groups. In fn_replaceBy , the function arguments equal these: First argument = $0 , second argument = $1 , et cetera.

The matched substring will be replaced by the return value of function fn_replaceBy . Using a function as a second parameter for replace allows very powerful applcations, such as an intelligent HTML parser .

See also: MDN: String.replace > Specifying a function as a parameter

It's not the prettiest solution, but you could replace the first occurrence with something arbitrary (like a placeholder) and chain replacements to fulfill the rest of the logic:

'-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

Produces:

-983247924234.01

This merely expands on the accepted answer for anyone looking for an example that can't depend on the first match/occurrence being the first character in the string.

 "l 5 0 l 0 10 l -5 0 l 0 -10".replace(/^\s+/, '').replace(/\s+l/g, '')

确保第一个'l'前面没有空格,并删除后跟'l'任何空格。

标记的分析服务程序实质上是错误的,第一次出现并不意味着字符串以该模式开头。

I found this solution at https://www.regextester.com/99881 , using a lookbehind pattern:

/(?<=(.*l.*))l/g

Or more generally

/(?<=(.*MYSTRING.*))MYSTRING/g

where MYSTRING is something that you want to remove.

(This may also be a useful string for removing all but the first occurrence of "Re:" in an email subject string, by the way.)

像这样的东西?

"l 5 0 l 0 10 l -5 0 l 0 -10".replace(/[^^]l/g, '')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM