0

I am horrible at Regex, what i want is to check if a string has the word http twice, for example : http://stackoverflow.com/questions/askhttp://stackoverflow.com/questions/ask, using the awesome feature of regex in javascript.

thanks.

MNS
  • 365
  • 1
  • 4
  • 16
  • 1
    Just use `indexOf`, duh – nhahtdh Jun 12 '13 at 16:37
  • If you want to check whether a particular url occours twice, it's impossible to do it using pure regex. However, it should be easy to do using string ops. – shashwat Jun 12 '13 at 16:41
  • /.*http.*http.*/ 0 or more character before first http, between the two https and after the last http – Balázs Édes Jun 12 '13 at 16:41
  • @shashwat: Occurring exactly twice can be done with regex, depending on how you do it, it can be beautiful or ugly... – nhahtdh Jun 12 '13 at 16:44
  • @nhahtdh A little research tells me that you're right: Javascript can refer to matched groups within the expression, which will give us what we need. Theoretically however, regex can't do this, because one will need a PDA for this, and a FA won't be able to. – shashwat Jun 12 '13 at 16:51
  • @shashwat: I think theoretical regex can do this (exactly n times), just that it is going to be ugly. – nhahtdh Jun 12 '13 at 16:57

5 Answers5

7
/http.*http/

Is the simplest expression that does this. That is http anywhere in the string followed by zero or more characters followed by http.

Explosion Pills
  • 176,581
  • 46
  • 285
  • 363
4

Although not exactly answering the question. Why not use indexOf() with offset, like so:

var offset = myString.indexOf(needle);
if(myString.indexOf(needle, offset)){
   // This means string occours more than one time
}

indexOf is quicker than regex. Also, it is a bit less exposed to special chars ruining the code.

Skarlinski
  • 1,991
  • 7
  • 26
  • I know i said regex in my question, but it was cuz i had no idea about 'indexOf', this is really helpful, thank youuuuu. – MNS Jun 12 '13 at 16:58
2

Another way, which can be extended to more than n times or exactly n times easily:

(inputString.match(/http/g) || []).length >= n

If you want to extend it to any literal string, you can use RegExp constructor with the input string after regex-escaping:

(inputString.match(new RegExp(escapeRegex(needle), 'g')) || []).length >= n

escapeRegex function replicated here for convenience:

function escapeRegex(input) {
    return input.replace(/[[\](){}?*+^$\\.|]/g, '\\$&');
}
Community
  • 1
  • 1
nhahtdh
  • 52,949
  • 15
  • 113
  • 149
  • Thanks a lot, that is exactly what i needed, cuz i said "twice" just to give a number, it could be 3 or more. – MNS Jun 12 '13 at 16:56
  • 2
    @user2463937: My answer was wrong, but no one actually comment... Just checked and fixed my answer. – nhahtdh Jun 12 '13 at 21:49
  • Like the extended regex version but shouldn't the `[` and `^` be escaped in `escapeRegex` like this `/[\[\](){}?*+\^$\\.|]/g` so that it doesn't get misinterpreted in some regex engines (jslint throws a warning on these)? – Xotic750 Jun 13 '13 at 13:28
  • @Xotic750: They don't need escaping. `^` only needs escaping if it is the first character in the character class. `[` doesn't actually needs escaping in JS (since there is no feature using `[` inside character class), but you can escape it if you like (since in other languages `[` may have special meaning inside character class). – nhahtdh Jun 13 '13 at 14:15
  • 1
    Ok, then I guess it is jslint complaining needlessly (as normal), but escaping them should not hurt, just to silence jslint. :) and +1 – Xotic750 Jun 13 '13 at 14:21
2

No need for a regex, you could use a little function like this that utilises String.indexOf and performs a word count.

EDIT: perhaps "word count" is a bad description and better would be "pattern matches"

Javascript

var testString = "http://stackoverflow.com/questions/askhttp://stackoverflow.com/questions/ask",
    testWord = "http";

function wc(string, word) {
    var length = typeof string === "string" && typeof word === "string" && word.length,
        loop = length,
        index = 0,
        count = 0;

    while (loop) {
        index = string.indexOf(word, index);
        if (index !== -1) {
            count += 1;
            index += length;
        } else {
            loop = false;
        }
    }

    return count;
}

console.log(wc(testString, testWord) > 1);

On jsfiddle

Xotic750
  • 20,394
  • 8
  • 50
  • 71
  • yes good idea .... 39 lines of code instead of one ... – solisoft Jun 13 '13 at 06:18
  • This example is fully functional, yours is not. This code is reusable, yours is not. This code counts all matches and return that value, yours does not. I'm not really concerned about line count, but I can count and you can not. – Xotic750 Jun 13 '13 at 10:55
  • Yes but he asked about checking http twice ... not counting match ? in that case function wc(string, word) { return string.match(RegExp("("+word+")")).length } will do the trick too (still one line and fully reusable and also functional) :p – solisoft Jun 13 '13 at 12:36
  • Quote from OP "Thanks a lot, that is exactly what i needed, cuz i said "twice" just to give a number, it could be 3 or more". The code you have now given was not as appeared in your answer. I could also make my function into a single line. The point was that I was giving an alternative to using a regex, which are known to behave differently across browsers (perhaps not in this case, but that is irrelevant). Your new code also misses `new` and it throws an error if no matches are found. So I thank you for your down vote and bid you farewell. – Xotic750 Jun 13 '13 at 12:49
  • I hope you wont feel bad for this down vote ... I got one too for my answer ... – solisoft Jun 13 '13 at 12:52
  • Yes you're right about the issue ... modify your answer then I'll up vote you again – solisoft Jun 13 '13 at 12:54
  • Not at all, your new code is also missing the `g` flag. What are you expecting me to modify? `console.log(wc(testString, testWord) > 2)`; – Xotic750 Jun 13 '13 at 12:54
  • well notice it's not a final answer, just a answer to your comment ;) – solisoft Jun 13 '13 at 12:55
  • It is now modified so that logging displays `true` or `false`, `true` if more than 1 – Xotic750 Jun 13 '13 at 13:09
0
// this code check if http exists twice
"qsdhttp://lldldlhttp:".match(/http.*http/);
solisoft
  • 654
  • 4
  • 12