Функция replace
возвращает новую строку с заменой, но если не было никаких слов для замены, возвращается исходная строка. Есть ли способ узнать, действительно ли это заменило что-либо отдельно от сравнения результата с исходной строкой?
Как узнать, что JavaScript string.replace() сделал что-нибудь?
Ответ 1
Простой вариант - проверить совпадения перед заменой:
var regex = /i/g;
var newStr = str;
var replaced = str.search(regex) >= 0;
if(replaced){
newStr = newStr.replace(regex, '!');
}
Если вы этого не хотите, вы можете злоупотреблять обратным вызовом replace
, чтобы добиться этого за один проход:
var replaced = false;
var newStr = str.replace(/i/g, function(token){replaced = true; return '!';});
Ответ 2
Сравнение строк до и после - самый простой способ проверить, не сделал ли он что-либо, в String.replace()
нет встроенной поддержки.
[надуманный пример того, как '==' может быть удалён, потому что это было неправильно]
Ответ 3
Если ваша замена имеет другую длину от искомого текста, вы можете проверить длину строки до и после. Я знаю, это частичный ответ, действительный только для подмножества проблемы.
ИЛИ
Вы можете выполнить поиск. Если поиск удался, вы замените на подстроке, начиная с найденного индекса, а затем перекомпоновите строку. Это может быть медленнее, потому что вы генерируете 3 строки вместо 2.
var test = "Hellllo";
var index = test.search(/ll/);
if (index >= 0) {
test = test.substr(0, index - 1) + test.substr(index).replace(/ll/g, "tt");
}
alert(test);
Ответ 4
В качестве обходного пути вы можете реализовать свою собственную функцию обратного вызова, которая будет устанавливать флаг и выполнять замену. Аргумент replacement
replace
может принимать функции.
Ответ 5
С помощью indexOf
вы можете проверить, содержит ли строка строку.
Похоже, вы можете использовать это.
Ответ 6
посмотрите на string.match() или string.search()
Ответ 7
Javascript replace
отклоняется дизайном. Зачем? Он не совместим с заменой строки в обратном вызове.
Например:
"ab".replace(/(a)(b)/, "$1$2")
> "ab"
Мы хотим проверить, что замена выполняется за один проход. Я представлял себе что-то вроде:
"ab".replace(/(a)(b)/, "$1$2", function replacing() { console.log('ok'); })
> "ab"
Реальный вариант:
"ab".replace(/(a)(b)/, function replacing() {
console.log('ok');
return "$1$2";
})
> ok
> "$1$2"
Но функция replacing
предназначена для приема $0, $1, $2, offset, string
, и нам нужно бороться с заменой "$ 1 $2". Решение:
"ab".replace(/(a)(b)/, function replacing() {
console.log('ok');
// arguments are $0, $1, ..., offset, string
return Array.from(arguments).slice(1, -2)
.reduce(function (pattern, match, index) {
// '$1' from strings like '$11 $12' shouldn't be replaced.
return pattern.replace(
new RegExp("\\$" + (index + 1) + "(?=[^\\d]|$)", "g"),
match
);
}, "$1$2");
});
> ok
> "ab"
Это решение не идеально. Сама замена строки имеет свои собственные WAT. Например:
"a".replace(/(a)/, "$01")
> "a"
"a".replace(/(a)/, "$001")
> "$001"
Если вы хотите заботиться о совместимости, вы должны прочитать spec и реализовать все свое безумие.