简体   繁体   中英

JS regular expresison add something before bracket

I have the following string:

@something {
  color: red;
  background: yellow;
}

I am trying to add heyaaa before the closing bracket, for example..

@something {
  color: red;
  background: yellow;
  heyaaa
}

I'm using gulp string replace to search a css file for @something and add the needed heyaaa string before the closing bracket.

I tried the following but does not work...

.pipe(replace('^(\@something\s*{(?:\n.*)*?\n)}', 'heyaaa'))

Other regular expressions work so I know there is nothing wrong with my setup.

The problem is in the second parameter of replace function: your code replaces what's matched with heyaaa instead of inserting heyaaa at the place you want.

You can simply do what follows, referring to $1 (first matched group ) in the second parameter ( replacement ):

 const input = `@something { color: red; background: yellow; } @otherthing { color: red; background: yellow; } ` const regex = /^(\\@something+\\s*{(?:\\n.*)*?\\n)}/gm const result0 = input.replace(regex, 'NEW TEXT TO BE INSERTED') // Original substitution const result1 = input.replace(regex, '$1 NEW TEXT TO BE INSERTED\\n}') // Fixed substitution console.log(result0) // Original result console.log(result1) // Fixed result 

UPDATED: EXPLANATION

I added m suffix for multi-line regex match and g suffix for multiple matching (without it the reagexp is applied on the first match only).

If you need to add NEW TEXT TO BE INSERTED at the end of each CSS class, you should change @something into @[^\\s] in the regex (see following snippet).

 const input = `@something { color: red; background: yellow; } @otherthing { color: red; background: yellow; } ` const regex = /^(\\@[^\\s]+\\s*{(?:\\n.*)*?\\n)}/gm const result = input.replace(regex, '$1 NEW TEXT TO BE INSERTED\\n}') // Fixed substitution console.log(result) // Fixed result 

You are capturing the part from the start until the last semicolon in a group and after that you are matching the closing curly brace. But to get that back in the replacement you have to refer to the capturing group. What you have matched will not be there because you are replacing what you have matched.

To fix your regex you could capture the last } in a group ^(\\@something\\s*{(?:\\n.*)*?\\n)(}) and in the replacement refer to those groups.

 const regex = /^(\\@something\\s*{(?:\\n.*)*?\\n)(})/gm; const str = `@something { color: red; background: yellow; }`; const subst = `$1 heyaa\\n$2`; const result = str.replace(regex, subst); console.log(result); 

To take the start of the string into account and the indentation of the last line, you could match the first line, then repeat while not looking at a new line followed by a } .

You could capture the whitespace characters at the start in a capturing group and refer to that in the replacement to match the indenting for heyaaa :

^(@[^{]+{\s*(?:(?!\n})(\s+).*\n)*)(})

Pattern explanation

  • ^ Start
  • ( Capture group
    • @[^{]+{\\s* Match @ , 1+t imes not { . Then match { and 0+ times a whitespace char
    • (?: Non capturing group
      • (?!\\n})(\\s+).*\\n Assert what is on the right is not a newline followed by a } . If that is the case, match whole line followed by a new line
    • )* Close group and repeat 0+ times
  • ) Close capturing group
  • (}) Capture Closing parenthesis
  • $ End

In the replacement you could use the 3 capturing groups:

$1$2heyaaa\n$3

Regex demo

Using the callback function, your code might look like:

.pipe(replace(/^(@[^{]+{\s*(?:(?!\n})(\s+).*\n)*)(})/, function(_,g1,g2,g3) { 
    return g1 + g2 + "heyaaa\n" + g3; }
    )
)

 const regex = /^(@[^{]+{\\s*(?:(?!\\n})(\\s+).*\\n)*)(})/gm; const str = `@something { color: red; background: yellow; }`; const subst = `$1$2heyaaa\\n$3`; const result = str.replace(regex, subst); console.log(result); 

One way is to capture everything before last } in a group and in callback function of replace use that captured group along with the value you want.

 let str = `@something { color: red; background: yellow; }` let op = str.replace(/^(@something\\s*[\\w\\W]+)}$/g,function(_,g1){ return g1 + ' heyya,\\n}' }) console.log(op) 

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