0
\$\begingroup\$

So I've got a regular expression parsing tcp responses from a music daemon. In case responses pile up I've come up with an expression to separate full responses from the data, however I'd like to also reference which choice was matched. Using capturing groups results in different numbers for each group, so is there a way to reference which alternation choice was matched besides that?

var patt = /((volume):\s\d+\n(.+\n)+?OK\n|OK\s(MPD)\s\d+\.\d+\.\d+|(OK)|(ACK).+\n)/;

This will match it, but I want to do different things with the separated response based on which match it was. I'd like to just have a switch case reference a single variable, but the only way I can think of to is:

var mycase = null;
var result = patt.exec(data);
if (result[2] == "volume")
    mycase= "volume";
else if (result[4] == "MPD")
    mycase= "MPD";
else if (result[5] == "OK")
    mycase= "OK";
else if (result[6] == "ACK")
    mycase= "ACK";

Is there a better way to do this?

\$\endgroup\$
2
  • \$\begingroup\$ Can you provide the data against which you're applying this pattern? \$\endgroup\$
    – hjpotter92
    Commented Dec 10, 2014 at 1:45
  • \$\begingroup\$ "volume: 5\nrepeat: 0\nrandom: 0\nsingle: 0\nconsume: 0\nplaylist: 333\nplaylistlength: 1\nmixrampdb: 0.000000\nstate: play\nsong: 0\nsongid: 2\ntime: 36522:0\nelapsed: 36521.742\nbitrate: 0\naudio: 44100:16:1\nOK\nACK [5@0] {} Letter expected\nOK\nOK MPD 0.18.0\n" This is 4 responses combined into a single string. \$\endgroup\$
    – Brian Ge
    Commented Dec 10, 2014 at 18:36

2 Answers 2

2
\$\begingroup\$

First of all you can use non capturing groups to simplify the indices

var patt = /(?:(volume):\s\d+\n(?:.+\n)+?OK\n|OK\s(MPD)\s\d+\.\d+\.\d+|(OK)|(ACK).+\n)/;

var mycase = null;
var result = patt.exec(data);
if (result[1] == "volume")
    mycase= "volume";
else if (result[2] == "MPD")
    mycase= "MPD";
else if (result[3] == "OK")
    mycase= "OK";
else if (result[4] == "ACK")
   mycase= "ACK";

With this the result of the regex will be one of these

[ "complete match",  "volume", undefined, undefined, undefined ]
[ "complete match", undefined,     "MPD", undefined, undefined ]
[ "complete match", undefined, undefined,      "OK", undefined ]
[ "complete match", undefined, undefined, undefined,     "ACK" ]

Now you can either use the OR operator to get the case

mycase = result[1] || result[2] || result[3] || result[4];

Or just use a loop (be sure to only use non capturing groups for anything else but your cases)

for(var i = 1; i < result.length; i++){
    mycase = mycase || result[i];
} 
\$\endgroup\$
1
  • \$\begingroup\$ Awesome, this is perfect. And now I know about non-capturing groups. Thanks for the help! \$\endgroup\$
    – Brian Ge
    Commented Dec 10, 2014 at 18:38
0
\$\begingroup\$

You can create a list of cases and if any of the items in the result list equals one of the cases than change the case.

var cases = ['volume', 'MPD', 'OK', 'ACK'],
  currentCase = 0,
  mycase = null,
  results = patt.exec(data);
results.forEach(function(result) {
  mycase = mycase || (cases[currentCase++] === result ? result : mycase);
});

If you know that volume will always be with index 2 and so on then:

var cases = [['volume',2], ['MPD', 4], ['OK', 5], ['ACK', 6]],
  mycase = null,
  results = patt.exec(data);
cases.forEach(function(testCase) {
  mycase = mycase || (testCase[0] === results[testCase[1]] ? results[testCase[1]] : mycase);
});
\$\endgroup\$
2
  • \$\begingroup\$ Sounds good, I'm having trouble understanding this line though: mycase = mycase || (testCase[0] === results[testCase[1]] ? results[testCase[1]] : mycase); \$\endgroup\$
    – Brian Ge
    Commented Dec 9, 2014 at 20:55
  • \$\begingroup\$ mycase equals to either mycase OR (if the first item in testCase equals the result[testCase[1]] than return that result otherwise return mycase). In other words, If mycase !== null return mycase Else If testCase[0] === results[testCase[1]] return results[testCase[1]] Else return mycase \$\endgroup\$
    – Eyal
    Commented Dec 9, 2014 at 21:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.