views:

244

answers:

3

I'm trying to extract the first user-right from semicolon separated string which matches a pattern.

Users rights are stored in format: LAA;LA_1;LA_2;LE_3;

String is empty if user does not have any rights.

My best solution so far is to use the following regex in regex.replace statement: .*?;(LA_[^;]*)?.*

(The question mark at the end of group is for the purpose of matching the whole line in case user has not the right and replace it with empty string to signal that she doesn't have it.)

However, it doesn't work correctly in case the searched right is in the first position: LA_1;LA_2;LE_3;

It is easy to fix it by just adding a semicolon at the beginning of line before regex replace but my question is, why doesn't the following regex match it?

.*?(?:(?:^|;)(LA_[^;]*))?.*

I have tried numerous other regular expressions to find the solution but so far without success.

A: 

You could just split the string first:

function getFirstRight(rights)
{
    return rights.split(";",1)[0] || "";
}
Joel Coehoorn
Sorry, the rights and regexps were badly formatted before you answered. In case of LAA;LA_1;LA_2;LE_3; it returns "LAA" but the correct one is "`LA_1`".
Lauri Oherd
A: 

I am not sure I get your question right, but in regards to the regular expressions you are using, you are overcomplicating them for no clear reason (at least not to me). You might want something like:

function getFirstRight(rights) {
  var m = rights.match(/(^|;)(LA_[^;]*)/)
  return m ? m[2] : "";
}
Sinan Taifour
Thanks! Somehow I overlooked the match-function and my "easy solution" had still a bug. :)I ported your idea to actionscript3 and it now has the following form:`public function getRole():String{ return (/(^|;)(LA_[^;]*)/.test(this._rightsList))? this._rightsList.match(/(^|;)(LA_[^;]*)/)[2] : "";}`
Lauri Oherd
A: 

To answer the specific question "why doesn't the following regex match it?", one problem is the mix of this at the beginning:

.*?

eventually followed by:

^|;

Which might be like saying, skip over any extra characters until you reach either the start or a semicolon. But you can't skip over anything and then later arrive at the start (unless it involves newlines in a multiline string).

Something like this works:

.*?(\bLA_[^;]).*

Meaning, skip over characters until a word boundary followed by "LA_".

epost
Thank you for an answer. Somewhy .*?(\bLA_[^;]*)?.* still does not match.. The question-mark in the end is for matching zero or one occurrence. If I remove it then it matches exactly one occurrence.I solved my problem by using match-function but I would still like to understand why the last regex does not match.
Lauri Oherd
It looks like there's an extra "*" in the one in your comment. Not sure if that got there before you tried it in your code, or if something else caused a problem for you initially. But anyway, I just double checked and it seems to work, both strings, and also both replace() and match():var reg = /.*?(\bLA_[^;]).*/var s1 = 'LAA;LA_1;LA_2;LE_3;';var s2 = 'LA_1;LA_2;LE_3;';alert(s1.replace(reg, '$1'));alert(s2.replace(reg, '$1'));alert(s1.match(reg)[1]);alert(s2.match(reg)[1]);
epost