4

I have found the answer for a case which returns the second part of the string, eg:

"qwe_fs_xczv_xcv_xcv_x".replace(/([^\_]*\_){**nth**}/, ''); - where is nth is the amount of occurrence to remove.

If nth=3, the above will return “xcv_xcv_x”

Details in this StackOverflow post: Cutting a string at nth occurrence of a character

How to change the above regular expression to return the first part instead (ie. “qwe_fs_xczv”)?

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
edaus
  • 179
  • 1
  • 1
  • 11

3 Answers3

2

You need to use end anchor($) to assert ending position.

"qwe_fs_xczv_xcv_xcv_x".replace(/(_[^_]*){nth}$/, ''); 
//            --------------------^-----------^--- here

console.log(
  "qwe_fs_xczv_xcv_xcv_x".replace(/(_[^_]*){3}$/, '')
)

UPDATE : In order to get the first n segments you need to use String#match method with slight variation in the regex.

"qwe_fs_xczv_xcv_xcv_x".match(/(?:(?:^|_)[^_]*){3}/)[0]

console.log(
  "qwe_fs_xczv_xcv_xcv_x".match(/(?:(?:^|_)[^_]*){3}/)[0]
)
In the above regex (?:^|_) helps to assert the start position or matching the leading _. Regex explanation here.

Another alternative for the regex would be, /^[^_]*(?:_[^_]*){n-1}/. Final regex would be like:

/^[^_]*(?:_[^_]*){2}/

console.log(
  "qwe_fs_xczv_xcv_xcv_x".match(/^[^_]*(?:_[^_]*){2}/)[0]
)
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
  • Almost there :-) I like the simplicity of your answer but this one cuts from the end. My string has unknown number of segments. How to change it to return only the first 3 segments from the left? – edaus May 06 '18 at 07:14
  • 1
    It works, thanks. I went with Ori Drori answer since it's the simplest. – edaus May 06 '18 at 07:26
1

If you want to use replace, then capture up to right before the third _ and replace with that group:

const re = /^(([^_]*_){2}[^_]*(?=_)).*$/;
console.log("qwe_fs_xczv_xcv_xcv_x".replace(re, '$1'));
console.log("qwe_fs_xczv_xcv_xcv_x_x_x".replace(re, '$1'));

But it would be nicer to use match to match the desired substring directly:

const re = /^([^_]*_){2}[^_]*(?=_)/;
console.log("qwe_fs_xczv_xcv_xcv_x".match(re)[0])
console.log("qwe_fs_xczv_xcv_xcv_x_x_x".match(re)[0])
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
1

Use String.match() to look from the start (^) of the string, for three sequences of characters without underscore, that might start with an underscore (regex101):

const result = "qwe_fs_xczv_xcv_xcv_x".match(/^(?:_?[^_]+){3}/);
console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209