2012-06-02 2 views
10

Я пишу набор RegExps для перевода селектора CSS в массивы идентификаторов и классов.Javascript RegExp группы, не связанные с захватом

Например, мне бы хотелось '# foo # bar' вернуть ['foo', 'bar'].

Я пытался добиться этого с

"#foo#bar".match(/((?:#)[a-zA-Z0-9\-_]*)/g) 

но он возвращает [ «#foo», «#bar»], когда без захвата префикса: следует игнорировать символ #.

Есть ли лучшее решение, чем нарезать каждую из возвращаемых строк?

+1

Вот однострочный: 'str.replace (/ [^ #] + | (# [a-zA-Z0-9 \ -_] *)/g, '$ 1'). Split ('# ') .slice (1) ' – Gumbo

+0

split не работает в ie8 – webaba

+2

@webaba Почему ie8 даже будет иметь значение для чего-либо в сентябре 2014 года, если это не конкретный запрос? – Vexter

ответ

11

Вы можете использовать .replace() или .exec() в цикле для построения массива.

С .replace():

var arr = []; 
"#foo#bar".replace(/#([a-zA-Z0-9\-_]*)/g, function(s, g1) { 
               arr.push(g1); 
              }); 

С .exec():

var arr = [], 
    s = "#foo#bar", 
    re = /#([a-zA-Z0-9\-_]*)/g, 
    item; 

while (item = re.exec(s)) 
    arr.push(item[1]); 
+0

Я буду использовать '.exec()', спасибо! –

+0

@ user969302: Добро пожаловать. Мне нравится работать лучше. –

4

Это соответствует #foo и #bar потому что внешней группы (# 1) захват. Группа (№ 2) не является, но это, вероятно, не то, что вы проверяете.

Если вы не использовали глобальный режим согласования, немедленным исправить будет использование (/(?:#)([a-zA-Z0-9\-_]*)/.

В режиме глобального согласования результат не может быть получен только в одной строке, потому что match ведет себя по-разному. Используя регулярные выражения только (т.е. не строковые операции), вы должны были бы сделать это следующим образом:

var re = /(?:#)([a-zA-Z0-9\-_]*)/g; 
var matches = [], match; 
while (match = re.exec("#foo#bar")) { 
    matches.push(match[1]); 
} 

See it in action.

+2

Обратите внимание: он использует глобальный режим согласования. – Gumbo

+0

Будет соответствовать ['#foo', '#bar'] при использовании в глобальном режиме. –

+0

@Gumbo: В Javascript вы никогда не можете расслабляться вокруг регулярных выражений ... спасибо за уведомление, переработал ответ. – Jon

1

К сожалению, нет просмотра назад утверждение в Javascript RegExp, в противном случае вы могли бы сделать это:

/(?<=#)[a-zA-Z0-9\-_]*/g 

Помимо добавления в какую-то новую версию Javascript, я думаю, что использование пост-обработки split - ваш лучший выбор.

2

Я не уверен, если вы можете сделать это, используя спичку(), но вы можете сделать это с помощью метода регулярного выражения в EXEC():

var pattern = new RegExp('#([a-zA-Z0-9\-_]+)', 'g'); 
var matches, ids = []; 

while (matches = pattern.exec('#foo#bar')) { 
    ids.push(matches[1]); // -> 'foo' and then 'bar' 
} 
2

Вы можете использовать отрицательное опережения утверждение:

"#foo#bar".match(/(?!#)[a-zA-Z0-9\-_]+/g); // ["foo", "bar"] 
+1

Он возвращает ['foo', 'bar'], но не будет искать #, поэтому "# foo # bar.foobar" .match (/ (?! #) [A-zA-Z0-9 \ -_] +/г); вернется ['foo', 'bar', 'foobar'] –

 Смежные вопросы

  • Нет связанных вопросов^_^