-2

Let's say I had a string "QQxaxbxcQQ", and I wanted to capture all groups of x followed by any character. I also only want to search between the QQ's (the string may include other things in it). I assumed this would have worked:

var matches = str.match(/QQ(x\w)+QQ/)

However, this only seems to return to me the last match (xc). Can you point me in the right direction?

EDIT: the first version of my question was oversimplified. Apologies to original responders. Edited to make it closer to my actual problem.

ekad
  • 14,436
  • 26
  • 44
  • 46
user200814
  • 275
  • 1
  • 3
  • 8

5 Answers5

1

The + operator is greedy. /(x\w)+/ should match the entire string 'xaxbxc', and the capturing group will contain the final value to match the (x\w) component. In this case 'xc'. If you wish to capture each consecutive match, /(x\w)+/ should instead be /((?:x\w)+)/. This moves the capturing group around the sequence instead of inside it. The (?: ) represents a non-capturing group.

EDIT:

If you want every instance of (x\w), not just consecutive instances, don't use the + operator or capturing groups. Just use a global regex: /x\w/g.

'QQxaxbQQxcQQ'.match(/x\w/g) yields ['xa, 'xb', 'xc'].

'QQxaxbQQxcQQ'.match(/((?:x\w)+)/) yields ['xaxb', 'xaxb'].

EDIT 2:

If you wish to search only between QQs, a split should be the fastest method. (Underscore helps a lot here.)

_.chain('xyQQxaxbQQxcQQxr'.split('QQ'))
.slice(1, -1)
.map(function (string) {
    return string.match(/x\w/g);
})
.flatten()
.compact()
.value()

yields ['xa', 'xb', 'xc']

Keen
  • 954
  • 12
  • 19
1

You only need to add g parameter at end of your regex. g flag returns an array containing all matches, in our case all matches of backreference (x\w)

In bold here: /QQ(x\w)+QQ/g

var matches = str.match(/QQ(x\w)+QQ/g)

matches is an array

look at this: http://jsfiddle.net/SZRSA/3/

freedev
  • 25,946
  • 8
  • 108
  • 125
0

If you want to capture all groups, use this :

var matches = str.match(/(x\w)/g)

output :

["xa", "xb", "xc"]

I made two changes :

  • removed the + as you seem to want each x followed by one char
  • added the g modifier to ask for all groups

Reference


EDIT : if what you want is to get your matches only when they're between QQ and QQ, you can do this :

var matches = str.split('QQ').filter(function(v,i){return i%2})
    .join(' ').match(/(x\w)/g)
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
0
'xaxbxc'.match(/x\w/g);

which returns

["xa", "xb", "xc"]

As the OP changed the question. now it's a duplication of JavaScript regular expressions and sub-matches.

Community
  • 1
  • 1
xiaoyi
  • 6,641
  • 1
  • 34
  • 51
0

Perhaps wrapping the repetition in a capturing group is what you want (capturing all instances of x\w concatenated together):

var matches = str.match(/QQ((x\w)+)QQ/)

This returns "xaxbxc" as matches[1]

John Dvorak
  • 26,799
  • 13
  • 69
  • 83