6

Is there a javascript string function that search a regex and it will start the search at the end?

If not, what is the fastest and/or cleanest way to search the index of a regex starting from the end?

example of regex:

/<\/?([a-z][a-z0-9]*)\b[^>]*>?/gi
1

7 Answers 7

4

Maybe this can be useful and easier:

str.lastIndexOf(str.match(<your_regex_here>).pop());
Sign up to request clarification or add additional context in comments.

2 Comments

This does work for the OP's RegExp; so it is correct. For clarity, though, note it won't work with all REs, namely ones with look ahead / behind. e.g. 'xhtml html'.match(/(?<=x)html/g). See Andreas's comment on the question for an implementation that handles this correctly.
This will throw an error if match() returns null. Add a conditional or use optional chain operator, e.g.: str.lastIndexOf(str.match(<your_regex_here>)?.pop());
2

Perhaps something like this is suitable for you?

Javascript

function lastIndexOfRx(string, regex) {
    var match = string.match(regex);

    return  match ? string.lastIndexOf(match.slice(-1)) : -1;
}

var rx = /<\/?([a-z][a-z0-9]*)\b[^>]*>?/gi;

console.log(lastIndexOfRx("", rx));
console.log(lastIndexOfRx("<i>it</i><b>bo</b>", rx));

jsFiddle

And just for interest, this function vs the function that you choose to go with. jsperf

This requires that you format your regex correctly for matching exactly the pattern you want and globally (like given in your question), for example /.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i will not work with this function. But what you do get is a function that is clean and fast.

Comments

1

You may create a reverse function like:

function reverse (s) {
  var o = '';
  for (var i = s.length - 1; i >= 0; i--)
    o += s[i];
  return o;
}

and then use

var yourString = reverse("Your string goes here");
var regex = new Regex(your_expression);
var result = yourString.match(regex);

Another idea: if you want to search by word in reverse order then

function reverseWord(s) {
   var o = '';
   var split = s.split(' ');

  for (var i = split.length - 1; i >= 0; i--)
    o += split[i] + ' ';
  return o;
}

var yourString = reverseWord("Your string goes here");
var regex = new Regex(your_expression);
var result = yourString.match(regex);

2 Comments

this is workable, but I want to know the index of the last occurrence of the regex directly. If there is no other faster method, then I'll probably take this as an answer
The result will returns the array, after that you'll need the last item of array.
1

Andreas gave this from the comment:

https://stackoverflow.com/a/274094/402037

String.prototype.regexLastIndexOf = function(regex, startpos) {
    regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
    if(typeof (startpos) == "undefined") {
        startpos = this.length;
    } else if(startpos < 0) {
        startpos = 0;
    }
    var stringToWorkWith = this.substring(0, startpos + 1);
    var lastIndexOf = -1;
    var nextStop = 0;
    while((result = regex.exec(stringToWorkWith)) != null) {
        lastIndexOf = result.index;
        regex.lastIndex = ++nextStop;
    }
    return lastIndexOf;
}

Which gives the functionality that I need, I tested my regex, and it is successful. So I'll use this

1 Comment

This was the answer years ago, but since javascript now supports some functionalities that are missing before, I updated the accepted answer.
0

It depends what you exactly want to search for. You can use string.lastIndexOf or inside the regexp to use $ (end of the string).

Update: try the regexp

/<\/?([a-z][a-z0-9]*)\b[^>]*>?[\w\W]*$/gi

2 Comments

the problem with lastIndexOf is that regex are not included in the parameter, it only allows strings
well, the updated still returns the first instance of the regex using str.search(/<\/?([a-z][a-z0-9]*)\b[^>]*>?[\w\W]*$/gi);
0
var m = text.match(/.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i);
if (m) {
    textFound = m[1];
    position = text.lastIndexOf(textFound);
}

Use .* to skip as much text as posible, capture the text found and search it with lastIndexOf

EDIT:

Well, if text is found, no need to search with lastIndexOf. m[0] contains the full coincidence (including all the initial padding), and m[1] the searched text. So position of found text is m[0].length - m[1].length

var m = text.match(/.*(<\/?([a-z][a-z0-9]*)\b[^>]*>?)/i);
if (m) {
    textFound = m[1];
    position = m[0].length - m[1].length;
}

Comments

-1

Assuming you're looking for a string 'token', then you need the position of 'token' that has no other 'token' following until the end of the string.

So you should compose your regex something like that:

$token = 'token';
$re = "/(?:$token)[^(?:$token)]*$/";

This will find your 'token' where no further 'token' can be found until string end. The "(?:" grouping simply makes the group non-storing, slightly speeding up performance and saving memory.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.