javascripttypescriptstringsubstringline-endings

How to find a substring index in a string with different line ending in Typescript


I have two strings

  1. abc\r\ndef
  2. c\nde

And I need to find index of string 2 inside string 1.

I can't obviously use indexOf(), so I need something that would work like it, but took different line endings into consideration.

I cannot modify the original string because I need substring index in the original string. If I replace all \r\n with \n it will mess up original indexes, so I would have to restore them somehow.


Solution

  • (FWIW, there's nothing TypeScript-specific about this question. Just JavaScript.)

    You can do it by converting the string you're looking for into a regular expression using the alternation \r\n|\r|\n everywhere it has any of those sequences, and being sure to escape the parts in-between (see this question's answers for that). When you use the exec method of the resulting regular expression on the first string, if it matches, the return value (let's call it match) will be a match result (enhanced array) with the index available as match.index and the matched text available as match[0].

    Example with TypeScript type annotations commented out:

    // From https://stackoverflow.com/a/3561711/157247
    function escapeRegex(string) {
        return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    
    function test(str/*: string */, substr/*: string*/) {
        // Split up the text on any of the newline sequences,
        // then escape the parts in-between,
        // then join together with the alternation
        const rexText = substr
            .split(/\r\n|\n|\r/)
            .map((part) => escapeRegex(part))
            .join("\\r\\n|\\n|\\r");
        // Create the regex
        const re = new RegExp(rexText);
        // Run it
        const match = re.exec(str);
        if (match) {
            console.log(`Found ${JSON.stringify(match[0])} at index ${match.index} in ${JSON.stringify(str)}`);
        } else {
            console.log(`Not found`);
        }
    }
    
    
    test("abc\r\ndef", "c\nde");