skip to Main Content

Having a string (URL path) as for example: /this/is/some/url I would like to remove the first occurrence of / and change the string after the second forward slash (in the example some) by another string let’s say is. The result should be this/is/a/url and this is what I have:

let myUrl = '/this/is/some/url';
let splitUrl = myUrl.split('/').filter(v => v !== '');

splitUrl[2] = 'a';
let newUrl = splitUrl.join('/');

console.log(newUrl); // this/is/a/url

But now I wanted to change that into a RegEx so I came up with this:

const myUrl = '/this/is/some/url';
const modifiedUrl = myUrl.replace(/[a-zA-Z0-9]/, 'a').replace(/^//, '');

console.log(modifiedUrl); // ahis/is/some/url

But the result is not what I want since it outputs: ahis/is/some/url. I’ll admit that I am not so good with RegEx.

A few SO posts here and here did not help me since I still did not get how to replace only the content after the second forward slash.

Can I get some help?

2

Answers


  1. You can use

    let myUrl = '/this/is/some/url';
    const modifiedUrl = myUrl.replace(//((?:[^/]*/){2})[^/]*/, '$1a');
    console.log(modifiedUrl); // this/is/a/url

    See this regex demo. Details:

    • / – a / char
    • ((?:[^/]*/){2}) – Group 1: two occurrences of any zero or more chars other than / + a / char
    • [^/]* – zero or more chars other than /.

    The replacement is the backreference to the Group 1 value + the new string that will be inserted in the resulting string.

    To also replace the next URL subpart, just add /[^/]* to the regex pattern:

    let myUrl = '/this/is/some/url';
    const str1 = 'content1';
    const str2 = 'content2'
    const rx = //((?:[^/]*/){2})[^/]*/[^/]*/;
    
    const modifiedUrl = myUrl.replace(rx, '$1' + str1 + '/' + str2);
    
    console.log(modifiedUrl); // this/is/content1/content2

    The main idea stays the same: capture the text before the text you want to replace, then just match what you need to replace, and – in the replacement – use a backreference to the text captured, and append the text to replace with.

    NOTE: If your replacement text contains a literal $ followed with a digit that you actually do not want to treat as a backreference, but as a literal text, you should add .replace(/$/g, '$$$$') to each variable, str1 and str2 in the code above.

    Login or Signup to reply.
  2. I would choose an approach which breaks the task into two

    • where the 1st replacement uses a regex which exclusively targets a string value’s leading slash … /^// … and …

    • where the 2nd replacement uses a regex which targets exactly the 3rd path-segment or path-partial … /(?<=^(?:[^/]+/){2})[^/]+/. The direct replacement here gets achieved by utilizing a positive lookbehind, where the latter targets a sequence of two following path-segments of the form xxx/yyy/.

    The advantage comes with being able of processing both path variants alike, the ones with leading slash and the ones without the latter.

    console.log(
      'this/is/some/url ...',
    
      'this/is/some/url'
        // see ... [https://regex101.com/r/jfcZBU/2]
        .replace(/^//, '')
        // see ... [https://regex101.com/r/jfcZBU/1]
        .replace(/(?<=^(?:[^/]+/){2})[^/]+/, 'a')
    );
    console.log(
      '/this/is/some/url ...',
    
      '/this/is/some/url'
        .replace(/^//, '')
        .replace(/(?<=^(?:[^/]+/){2})[^/]+/, 'a')
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    In case of combining/merging both regex patterns, also in favor of not having to use a positive lookbehind (though every relevant browser meanwhile does support this feature), the regex then becomes more complex, therefore more difficult to read … /^/*((?:[^/]+/){2})[^/]+/.

    const regXPathCapture =
      // see ... [https://regex101.com/r/jfcZBU/3]
      /^/*((?:[^/]+/){2})[^/]+/;
    
    console.log(
      "'this/is/some/url'.replace(regXPathCapture, '$1a') ...",
      'this/is/some/url'.replace(regXPathCapture, '$1a')
    );
    console.log(
      "'/this/is/some/url'.replace(regXPathCapture, '$1a') ...",
      '/this/is/some/url'.replace(regXPathCapture, '$1a')
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search