2013-07-22 6 views
4

В регулярном выражении, которое использует OR (pipe), есть ли удобный способ для получения части выражения, которое соответствует.Возвращает часть регулярного выражения, которое соответствует

Пример:

/horse|caMel|TORTOISe/i.exec("Camel"); 

возвращается Camel. Я хочу caMel.

Я понимаю, что я мог бы перебирать варианты вместо использования одного большого регулярного выражения; это будет иметь больший смысл. Но мне интересно узнать, можно ли это сделать так.

+0

Чтобы быть ясным, вы пытаетесь вернуть регулярное выражение, а не строку со строкой? – Mathletics

+0

Исходя из этого примера, он вернул то, что соответствовало. Вы явно сказали регулярному выражению, чтобы игнорировать текст ** ** и ** верблюд ** соответствовали этому. Таким образом, он вернул ввод строки. –

ответ

5

Очень просто, нет.

Соответствие регулярных выражений относится к вашей входной строке, а не к тексту, используемому для создания регулярного выражения. Обратите внимание, что этот текст вполне может быть потерян и теоретически даже не нужен. Эквивалент согласовань может быть построена из чего-то вроде этого:

var test = function(str) { 
    var text = str.toLowerCase(); 
    return text === "horse" || text === "camel" || text === "tortoise"; 
}; 

Другим способа думать об этом является то, что составление регулярных выражений может развестись логикой функции от их текстового представления. Это однонаправлено.

Извините.

3

В Javascript RegExp нет встроенного способа; без изменения вашего выражения. Самое близкое, что вы можете получить, это source, который просто вернет все выражение в виде строки.

Поскольку вы знаете, что выражение представляет собой серию | OR с, вы могли бы захватить группы, чтобы выяснить, какие группы совпадают, и объединить, что с .source, чтобы узнать содержимое этой группы:

var exp = /(horse)|(caMel)|(TORTOISe)/i; 
var result = exp.exec("Camel"); 
var match = function(){ 
    for(var i = 1; i < result.length; i++){ 
     if(result[i]){ 
      return exp.source.match(new RegExp('(?:[^(]*\\((?!\\?\\:)){' + i + '}([^)]*)'))[1]; 
     } 
    } 
}(); 

// match == caMel 

Также чрезвычайно легко (хотя и несколько непрактично) написать RegExp-движок с нуля, вы могли бы технически добавить эту функциональность. Это будет намного медленнее, чем использование реального объекта RegExp, поскольку весь движок должен интерпретироваться во время выполнения. Тем не менее, он мог бы возвращать точно подобранную часть выражения для любого регулярного выражения и не ограничиваться тем, что состоит из серии | OR.

Лучший способ решить проблему, однако, вероятно, не использовать цикл или регулярное выражение на всех, но вместо того, чтобы создать объект, где вы используете каноническую форму для ключа:

var matches = { 
    'horse': 'horse', 
    'camel': 'caMel', 
    'tortoise': 'TORTOISe' 
}; 

// Test "Camel" 
matches['Camel'.toLowerCase()]; // "caMel" 
2

Это даст требуемое значение без зацикливания:

var foo, pat, tres, res, reg = /horse|caMel|TORTOISe/i; 
foo = reg.exec('Camel'); 

if (foo) { 
    foo = foo[0].replace(/\./g, '\\.'); 
    pat = new RegExp('\\|' + foo + '\\|', 'i'); 
    tres = '|' + reg.source + '|'; 
    res = tres.match(pat)[0].replace(/\|/g, ''); 
} 

alert(res); 

Если нет матча, теперь вы получите undefined, хотя это легко изменить на что-то другое.

+1

Это будет работать для одного тестового примера, но это не сработает для чего-то вроде '/ CAmel | caME | horse/i' с укусом« Came »(он вернет« CAme »вместо« caME »). – Paulpro

+0

@Paulpro Неудачно вы правы с этим.Я проверяю, есть ли что-то, что я могу исправить, если он не может (или я не могу), я удалю ответ. – Teemu

+0

Он также потерпел бы неудачу, если бы 'foo' оказалось более сложным выражением, включая символы, значимые в синтаксическом анализе регулярных выражений. –

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