RegEx replace возвращает неожиданный результат без.*
Я пытаюсь создать регулярное выражение, которое выполняет следующие преобразования:
Apple Orange
>AO
Load Module
>LM
anApple Orange
>O
toLoad Module
>M
Я нашел подходящий образец, но заметил странное поведение. Вот моя первоначальная попытка:
/^([A-Z])?[^ ]* ([A-Z])/
Выполнение замены в третьем (и четвертом) тестовом примере с этим выражением дает мне удивительный результат:
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
Почему это удивительно? Ну, первая группа, очевидно, не совпадает, поскольку строка не начинается с заглавной буквы, а вторая группа выбирает только одну заглавную букву: ([A-Z])
не все после него ([A-Z].*)
К моему удивлению, добавив .*
сразу после последнего захвата группа дала мне правильный результат:
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z]).*/,'$1$2')
> "O"
Почему это происходит за пределами моего понимания JS и регулярных выражений. Я очень рад узнать, что за темная магия вызывает у нас [A-Z]
вернуть несколько, и даже несколько строчных букв.
Вот работающая демонстрация:
var testCases = [
'Apple Orange',
'Load Module',
'anApple Orange',
'toLoad Module'
],
badregex = /^([A-Z])?[^ ]* ([A-Z])/,
goodregex = /^([A-Z])?[^ ]* ([A-Z]).*/;
document.onreadystatechange = function(n){
if (document.readyState === "complete"){
for (var i=0,l=testCases.length; i<l; i++){
var p = document.createElement('p'),
testCase = testCases[i];
p.innerHTML = ""+testCase+" > "+testCase.replace(badregex,'$1$2')
document.body.appendChild(p);
}
document.body.appendChild(document.createElement('hr'));
for (var i=0,l=testCases.length; i<l; i++){
var p = document.createElement('p'),
testCase = testCases[i];
p.innerHTML = ""+testCase+" > "+testCase.replace(goodregex,'$1$2')
document.body.appendChild(p);
}
}
}
3 ответа
Я бы хотел,
> "Apple Orange".replace(/(?:^|\s)([A-Z])|./g, "$1")
'AO'
Не усложняй вещи. Просто запишите все заглавные буквы, которые существуют сразу после пробела или в начале. А затем сопоставьте все оставшиеся символы. Теперь замените все соответствующие символы на $1
, Обратите внимание, что все совпадающие символы заменяются символами, присутствующими внутри запасной части.
Зачем?
'anApple Orange'.replace(/^([A-Z])?[^ ]* ([A-Z])/,'$1$2')
> "Orange"
([A-Z])?
проверяет наличие дополнительной заглавной буквы в начале. Там нет такой вещи. Таким образом, он захватывает пустую строку.[^ ]*
соответствует нулю или более непробельных символов.<space>
соответствует пробелу([A-Z])
захватывает только первую букву оранжевого цвета.- Теперь, заменив все сопоставленные символы с
$1
-> пустая строка$2
->O
дам тебеOrange
Ваш первый пример соответствует anApple O
, $1
пусто, потому что ^([A-Z])?
не является обязательным и не соответствует и $2
является O
так ты заменишь anApple O
от O
в строке anApple Orange
и это приведет к Orange
Вместо того, чтобы использовать replace
со сложным регулярным выражением вы можете использовать очень простое регулярное выражение с match
и использовать join
чтобы получить желаемый результат:
'anApple Orange'.match(/\b([A-Z])/g).join('')
//=> O
'Apple Orange'.match(/\b([A-Z])/g).join('')
//=> AO