0

I have a set of structured data into a string and I need to iterate over it through regular espression in Javascript.

This is an example of the data:

|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4

I need to parse them and create a structured object (or an array) like this:

myObject.KEY1 = "VALUE 1"
myObject.KEY2 = "VALUE 2"
myObject.KEY3 = "OTHER VALUE WITH ANY CHARACTER LIKE SPACES, AND WHAT YOU WANT"
myObject.KEY4 = "VALUE4"

I've got the keys with that simple regex:[|](.+?)[|] but I don't know how to iterate through them and thei respective values.

4
  • 1
    If you are allowed to have your delimiter | in your data then you must have some way to escape it. There is absolutely no way to distinguish that |PIPES| is not a new key, followed by a new value. Even if keys have a very rigid format, I can always put something that looks like a key in the data. e.g. |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, \|PIPES\| AND WHAT YOU WANT Commented Jan 20, 2015 at 21:33
  • You are right. I've looked through the data and there isn't that occourrence. So forgot the meta-pipe problem ;) Commented Jan 20, 2015 at 21:41
  • @Pennywise83 What kind of source is delivering data in this format? Commented Jan 20, 2015 at 21:47
  • Why regex? This seems like a simple string manipulation problem. Commented Jan 20, 2015 at 21:56

4 Answers 4

2

I'm going to assume that a key is defined by the expression \|KEY[0-9]+\|, since that's the simplest way to include |KEY1| through |KEY4| while also excluding |PIPES|.

If your goal is to use a loop and regex matches, as opposed to a single convoluted regex or doing actual parsing with functions like indexOf(), then this can be done with negative lookahead.

var x = "|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4";

var map = {};

while(x.length > 0) {
    var key = x.match(/\|KEY[0-9]+\|/)[0];
    x = x.substr(key.length);
    var value = x.match(/(.(?!\|KEY[0-9]+\|))*/)[0];
    x = x.substr(value.length);
    map[key] = value;
}

alert(JSON.stringify(map, null, 4));

http://jsfiddle.net/eyL7yhwr/

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

Comments

2

This will do it.

//using regex
var keyString = "|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4"
var cases = keyString.match(/[^|]+/g)
var myObject = {};
if (cases.length > 0)
  {
     for (var i = 0; i < cases.length; i += 2)
     {
       myObject[cases[i].toString()] = cases[i+1].trim();
     }
  }
  
  document.write(JSON.stringify(myObject));

3 Comments

The sample output in the question shows that "|PIPES|" is not supposed to be one of the keys, so this answer is incorrect (unless he changes his mind about that requirement).
@Ixrec "You are right. I've looked through the data and there isn't that occourrence. So forgot the meta-pipe problem ;)" as commented by the OP.
In retrospect it's hard to tell whether he actually wanted "|PIPES|" to be a key or not, so I'll just +1 and we'll call it a draw.
0

You can do something like this:

var s = "|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4";

s.match(/\|(KEY\d+)\|.*?(?=\|KEY\d|$)/g).reduce(function (res, v) { 
  var match = v.match(/(KEY\d+)\|(.*?)\s*$/);
  res[match[1]] = match[2];
  return res;
}, {})

another solution even easier:

var s = "|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4";

var v, res = {}, match = s.match(/\s*\|KEY\d+\|\s*|.+?(?=\s*\|KEY\d|$)/g);
while(v = match.shift()) 
  res[v.replace(/^[\s|]*|[\s|]*$/g, '')] = match.shift();

Comments

0

Something like exec and /[^|]+/g will get you a nice array.

var str = "|KEY1|VALUE 1 |KEY2| VALUE 2 |KEY3| OTHER VALUE WITH ANY CHARACTER LIKE SPACES, |PIPES| AND WHAT YOU WANT |KEY4| VALUE4";

var re = /[^|]+/g;

var arr = [];

while ((arr = re.exec(str)) !== null){
  console.log(arr[0].trim());
}

fiddle

It's a bit simpler than some other regex here, and I think it's a bit more readable. I also used trim(), which you'll have to use the polyfill if you want to support before IE9.

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.