1

I have these couple lines that I would like to match and right now I use multiple regexes to match them all, however I'm wondering if it is possible to match both in one regex:

@@Author:logan
//and these, three variations
@@tags:markdown,github,repetitivetag, tagwithsubtags:subtag, another:subtag:subtag2:repeating:this:repeating,repetitivetag,repetitivetag:withsubby,repetitivetag:withsubtag
@@tags:markdown;github;repetitivetag;tagwithsubtags:subtag,another:subtag:subtag2:repeating:this:repeating;repetitivetag;repetitivetag:withsubby;repetitivetag:withsubtag
@@tags:markdown;git-hub;repetitive-tag;tag_with_sub-tags:sub_tag,another:sub_tag:sub-tag2:repeating:this:repeat-_-_-ing;repetitive-tag;repetitive_tag:with_subby;repetitive_tag:with_subtag

What I do first is to match the @@NAME:VALUE part:

  • /^(?:@@)(\w+):(.*.)(?:\n+|$)/gm

let's say the first group is NAME and second group is VALUE.

If NAME is tags then I match the following regex in VALUE:

  • /(\w+)((?=,|;)|(:\w[\w|\-]+\w){0,}|)/g

This matches several groups that are like TAG;TAG;TAG ... or TAG,TAG,TAG ... in VALUE that we matched before

Then I match each TAG with this to get the SUBTAG

  • /(:)(\w[\w|\-]+\w)(?=:|)/g

Now that matches groups like :SUBTAG:SUBTAG:SUBTAG ... within TAG that we matched above

In Summary

I want to match

  • (@@)(NAME)(:)(VALUE)
    • (TAG)(;)(TAG)(;)(TAG) ... in VALUE
      • (:)(SUBTAG)(:)(SUBTAG))(;) in tag

example

  1. @@Author:logan should be able to get Name = Author, Value = logan

  2. if value is multiple, like if its seperated by comma or semi-colon then matching something like @@tags:tag1;tag2 should be able to get

    Name = Tags, `Value = ['tag1','tag2']

  3. if value has a subvalue such as

    @@Author:logan:lastname

    or this as its intended purpose

    @@Tags:tag1:subtag;tag2:subtag1:subtag2 should be able to get:

    Name = Author, Value = [{logan : [lastname]}] and

    Name = Tags, Value = [{tag1 : [subtag]}, {tag2 : [subtag1, subtag2]}]

How can I match groups within groups and only if they exist?

3
  • 3
    Using one regex only would lead to an unmaintainable monster imho... By the way, ,|; can be replaced with [,;] Commented Jan 13, 2013 at 9:28
  • ah thanks, initially I'm writing a ace highlighter for this so that's why I was wondering if I could use a one liner. So for these purposes it is more common to capture groups then process that group and so on? Am I on the right track? Commented Jan 13, 2013 at 9:49
  • I don't know whether this is more common, however it will certainly be easier :) Commented Jan 13, 2013 at 10:09

1 Answer 1

2

This gives exactly the output you want:

// Examples:
var a='@@Author:logan';
var b='@@tags:tag1;tag2';
var c='@@Author:logan:lastname';
var d='@@Tags:tag1;tag2:subtag1:subtag2';
var hard1='@@tags:markdown,github,repetitivetag, tagwithsubtags:subtag, another:subtag:subtag2:repeating:this:repeating,repetitivetag,repetitivetag:withsubby,repetitivetag:withsubtag';
var hard2='@@tags:markdown;github;repetitivetag;tagwithsubtags:subtag,another:subtag:subtag2:repeating:this:repeating;repetitivetag;repetitivetag:withsubby;repetitivetag:withsubtag';
var hard3='@@tags:markdown;git-hub;repetitive-tag;tag_with_sub-tags:sub_tag,another:sub_tag:sub-tag2:repeating:this:repeat-_-_-ing;repetitive-tag;repetitive_tag:with_subby;repetitive_tag:with_subtag';

function tags(a){
    // Gets the name:
    var name=a.match(/^@@.*?(:|.$)/);
    if(!name) return;
    var temp=a.indexOf(':')+1;
    name=name[0].substring(2).replace(':','');
    // Returns the name if thats all there is:
    if(!temp) return name;
    a=a.substring(temp);
    // Gets the value:
    var value=a.split(/[,;]/);
    if(value.length==1&&value[0].indexOf(':')==-1)
        value=value[0];
    else for(var i=0;i<value.length;i++) if(value[i].indexOf(':')!=-1) {
        // Gets the subtags if they exist:
        temp={};
        a=value[i].split(':');
        // .shift() will remove/return the first of the array
        temp[a.shift()]=a;
        value[i]=temp;
    }
    return {name:name,value:value};
}
console.log([tags(a),tags(b),tags(c),tags(d),tags(hard1),tags(hard2),tags(hard3)]);

This was really cool to code for actually. I'm not sure if your question said exactly what you wanted, but if it didn't, then everything should be really easy to modify. Hope you like the else-for-if statement!

Sign up to request clarification or add additional context in comments.

5 Comments

I'm glad you had fun coding it :) Thank you for your answer, it is good to know another alternative approach to this. As my purpose lies towards writing a syntax highlighter for ace I cannot use this as a whole but would have to break this apart into three part rule. However it is good to know another way of doing this that may help me break it down better :)
Do you just want the name and value parts separated? Or do you want name, tags, and subtag parts separated? And just to get it straight, the value is representative of tags and subtags altogether, right?
Well, to clear it up, the results in your code are exactly how I wanted them to be parsed. The problem is when writing syntax highlighter for ace with this tool I need to chain them somehow in a clever manner so that it should look for @@key:value then if there is a value:subvalue then it should highlight subvalue, then if there is another value like in @@key:value:subvalue;anothervalue:anothersubvalue then it should get the other value and so on... What you did is just a different color of what I do to parse it :)
It didn't fit in one comment... Well my question was if there was a way to capture groups within groups in just one regex. Just pretend that these are all regexes: (@@ part)(:)(key)(if there is :\w+ then (:)(value part)) and so on... I guess the problem is that captured array size would be dynamic... Anyways here is the gist that shows how to test it gist.github.com/4527881
Yeah I didn't quite have time to figure out another solution... Though I do understand the problem more now.

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.