0

I am using the following regex in a custom selector in jQuery

$.expr[":"].matchRegex = $.expr.createPseudo(function(arg) {
    return function( elem ) {
        return $(elem).text().match(new RegExp(arg, 'i')) != null;
    };
});

However, since javascript does not allow lookbehind, I am unable to pass this regex:

/\b(?<!')(s|otherword)s?\b/

The expression should match at least one s if it not preceded by a single quote. The s|otherword part in the expression is actually provided by the user, so I have to work with that.

I understand how creating a custom function (Javascript: negative lookbehind equivalent?) can be a workaround for the lookbehind (replace example) but I am unable to get this to work.

I tried modifying my selector to this:

$.expr[":"].matchRegex = $.expr.createPseudo(function(arg) {
    return function( elem ) {
        return ($(elem).text().match(new RegExp(arg, 'i')) != null) ? false : true;
    };
});

and changing the regex expression to this:

/\b(')(s|otherword)s?\b/

but this will return all elements with text that do not contain 's.

Can I use the match method with a callback function? If not, how can the jQuery selector be modified to accommodate this?

Any insight and help always greatly appreciated.

Thank you!

Community
  • 1
  • 1
  • The workarounds are useful for testing whether a string matches, they're not appropriate for searching and replacing. – Barmar Jan 11 '15 at 21:32
  • So... your *actual* question is "how to emulate look-behind in JavaScript regular expressions"? Because jQuery doesn't seem to have a whole lot to do with your problem. – Tomalak Jan 11 '15 at 21:45
  • Thanks @Barmar for editing and responding so quickly. I am not looking to replace the text - all I want is to match it (I referred to replacing because the workaround solution provided that method as an example). How does matching differ than searching in the above scenario? Is it because I am using a custom selector? – Nikolaos Alexiou Jan 11 '15 at 21:45
  • @Tomalak Yes, that is what I am trying to achieve. If emulating requires a custom function, I was not sure whether or not the custom selector/jQuery complicated things. – Nikolaos Alexiou Jan 11 '15 at 21:49
  • @NikolaosAlexiou The difference is that matching needs to omit the part of the string that doesn't match the negative lookaround from the match. The workarounds don't achieve that. – Barmar Jan 11 '15 at 21:52
  • 1
    On an unrelated note, `return (x === null) ? false : true` is an antipattern. Use `return x !== null;`. In that particular situation shown above I'd even simply `return new RegExp(arg, 'i').test($(elem).text());`. – Tomalak Jan 11 '15 at 22:02

1 Answers1

0

The expression should match at least one s if it not preceded by a single quote.

Since you really don't want to work with the matches, only test if there is a match at all, you don't really need a lookbehind. You only need to make sure that it works at the start of the string.

(?:^|[^'])(s|otherword)s?\b

That's all, really.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Thanks! I believe this works. Is it easy to explain how the non-capturing group differs than `\b`? – Nikolaos Alexiou Jan 11 '15 at 22:09
  • `\b` matches a word boundary (that is: The zero-width position between a `\w` and a `\W`). Your original definition *"only if not preceded by a single quote"* did not say *"and also there must be a word boundary before that single quote"*, so I removed the leading `\b`. (Because otherwise it would have *required* one of `[a-zA-Z0-9_]` before the single quote - and I figured this was likely not your intention.) – Tomalak Jan 11 '15 at 22:16
  • Ok. I just got to test this regex a little bit. This regex will match an s that is not a complete word. This is why I had the `\b` in the front of the expression. I want to match `s`, `otherword` only when they are whole words. I think the main problem with `\b` is that is uses the single quote as a word boundary. – Nikolaos Alexiou Jan 11 '15 at 22:43
  • You beat me to the punch ~ just noticed your comment! So, how do I work around that? For example, for the following string `The children's place and s.`, the regex should match the last `s` but not the one after `children's` – Nikolaos Alexiou Jan 11 '15 at 22:53
  • Would this be the appropriate way? `(?:^|[a-z0-9_]|[^'])\b(s|otherword)s?\b` – Nikolaos Alexiou Jan 11 '15 at 23:08
  • I'm not sure what you mean. My regex *does* only match the last `s`, and not the one in `children's`. – Tomalak Jan 11 '15 at 23:16
  • 1
    So sorry. I was testing the regex against my code and could not figure out why it was not working. Apparently, the text that I was testing against contained this `’` which is not a single quotation mark but a right single quotation mark! I believe this regex will work: `(?:^|[^’'])\b(s|otherword)s?\b` – Nikolaos Alexiou Jan 11 '15 at 23:42