Главная » Статьи » 3 способа заменить все вхождения строки в JavaScript

3 способа заменить все вхождения строки в JavaScript

3 способа заменить все вхождения строки в JavaScript

От автора: JavaScript не предоставляет простой способ заменить все вхождения строк. Ирония заключается в том, что Java, который послужил источником вдохновения для JavaScript в первые дни, использует метод replaceAll() для строк с 1995 года!

В этом посте описываются 2 обходных пути для замены всех вхождений строк в JavaScript: разбиение и объединение строк, и replace() в сочетании с регулярным выражением.

В конце, вы прочтете о новом предложении String.prototype.replaceAll() (на этапе 3), которое реализует метод replaceAll() для строк.

1. Разбивка и объединение массива

Первый подход для замены всех вхождений строки состоит из 2 этапов:

Разбить строку на части по строке поиска.

После этого соединить части назад, добавив заменяющую строку между частями.

Например, давайте заменим + на — в строке ’1+2+3′. Сначала ’1+2+3′ делится на +, что дает [‘1’, ‘2’, ‘3’] отдельно. Затем эти части соединяются через — между ними, что дает ’1-2-3′. Вот как вы можете использовать методы split() и join() для достижения этого в JavaScript:

const search = 'duck';
const replaceWith = 'goose'; const result = 'duck duck go'.split(search).join(replaceWith);
result; // => 'goose goose go'

‘duck duck go’.split(‘duck’) разбивает строку на части: [», ‘ ‘, ‘ go’].

Затем эти части соединяются [», ‘ ‘, ‘ go’].join(‘goose’), с добавлением ‘goose’ между ними, что дает строку ‘goose goose go’.

Вот обобщенная вспомогательная функция, которая использует разбиение и объединение:

function replaceAll(string, search, replace) { return string.split(search).join(replace);
} replaceAll('abba', 'a', 'i'); // => 'ibbi'
replaceAll('go go go!', 'go', 'move'); // => 'move move move!'
replaceAll('oops', 'z', 'y'); // => 'oops'

Этот подход требует преобразования строки в массив, а затем обратно в строку. Это скорее обходной путь, чем хорошее решение.

2. replace() с глобальным регулярным выражением

String.prototype.replace(regExp, replaceWith) ищет вхождения с помощью регулярного выражения regExp, а затем заменяет все совпадения на строку replaceWith.

Вы должны включить глобальный флаг в регулярном выражении, чтобы метод replace() заменял все вхождения шаблона. Вот как сделать:

В регулярных выражениях литералы добавляют g после раздела флагов: /search/g

В случае конструктора регулярного выражения используйте аргумент флага: new RegExp(‘search’, ‘g’)

Давайте заменим все вхождения ‘duck’ на ‘goose’:

const searchRegExp = /duck/g;
const replaceWith = 'goose'; const result = 'duck duck go'.replace(searchRegExp, replaceWith); result; // => 'goose goose go'

Литерал регулярного выражения /duck/g соответствует строке ‘duck’ и имеет включенный глобальный режим.

‘duck duck go’.replace(/duck/g, ‘goose’) заменяет все вхождения подстрок /duck/g на ‘goose’.

Вы можете легко выполнить замены без учета регистра, добавив к регулярному выражению флаг i:

const searchRegExp = /duck/gi;const replaceWith = 'goose'; const result = 'DUCK duck go'.replace(searchRegExp, replaceWith); result; // => 'goose goose go'

Снова посмотрим на регулярное выражение: /duck/gi. Регулярное выражение включило поиск без учета регистра i, наряду с глобальным флагом g. /duck/gi соответствует ‘duck’, а также ‘DUCK’, ‘Duck’ и так далее.

‘DUCK duck go’.replace(/duck/gi, ‘goose’) заменяет все вхождения подстрок /duck/gi без учета регистра на ‘goose’.

Хотя регулярные выражения заменяют все вхождения строки, на мой взгляд, этот подход слишком тяжелый.

2.1 Регулярное выражение из строки

Использование подхода с регулярными выражениями неудобно, когда строка поиска определяется во время выполнения. При создании регулярного выражения из строки вы должны экранировать символы — [ ] / { } ( ) * + ? . \ ^ $ |.

Вот пример проблемы:

const search = '+'; const searchRegExp = new RegExp(search, 'g'); // Throws SyntaxErrorconst replaceWith = '-'; const result = '5+2+1'.replace(searchRegExp, replaceWith);

Приведенный выше фрагмент кода пытается преобразовать строку поиска ‘+’ в регулярное выражение. Но ‘+’ является недопустимым регулярным выражением, поэтому выдается SyntaxError: Invalid regular expression: /+/.

Использование символа ‘\\+’ решает проблему. Для простой замены всех вхождений задача, связанная с регулярными выражениями и экранированием строки поиска, является слишком сложной.

2.2 replace() строку

Если первый аргумент replace(search, replaceWith) является строкой, то метод заменяет только первое вхождение в search.

const search = 'duck';const replaceWith = 'goose'; const result = 'duck duck go'.replace(search, replaceWith); result; // => 'goose duck go'

‘duck duck go’.replace(‘duck’, ‘goose’) заменяет только первое вхождение ‘duck’ на ‘goose’.

3. Метод replaceAll()

Наконец, новое предложение String.prototype.replaceAll () (на этапе 3) переносит replaceAll() метод на строки. Строковый метод replaceAll(search, replaceWith) заменяет все вхождения строки search на replaceWith без каких-либо обходных методов.

Давайте заменим все вхождения ‘duck’ на ‘goose’:

const search = 'duck'
const replaceWith = 'goose'; const result = 'duck duck go'.replaceAll(search, replaceWith); result; // => 'goose goose go'

‘duck duck go’.replaceAll(‘duck’, ‘goose’) заменяет все вхождения строки ‘duck’ на ‘goose’. Это простое решение.

3.1 Разница между replaceAll() и replace()

Строковые методы replaceAll(search, replaceWith) и replace(search, replaceWith) ведут себя одинаково, за исключением двух моментов:

Если аргумент search является строкой, replaceAll() заменяет все вхождения из search на replaceWith, в то время как replace() только первое вхождение

Если аргумент search является неглобальным регулярным выражением, replaceAll() генерирует исключение TypeError.

4. Заключение

Замена всех вхождений строк должна быть простой задачей. Однако в JavaScript давно не было способа сделать это. Один из подходов заключается в том, чтобы разбить строку на куски с помощью строки поиска, объединить их обратно строку, размещая строку замены между кусками: string.split(search).join(replaceWith). Этот подход работает, но он является хаком.

Другой подход заключается в использование String.prototype.replace() с регулярным выражением с включенным глобальным поиском: string.replace(/SEARCH/g, replaceWith).

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

Наконец, метод String.prototype.replaceAll() может легко заменить все вхождения строки напрямую: string.replaceAll(search, replaceWith). Это предложение на третьем этапе, но, надеюсь, оно скоро появится в новом стандарте JavaScript.

Я рекомендую использовать replaceAll() для замены строк. Вам понадобится полифилл, чтобы использовать метод.

Автор: Dmitri Pavlutin

Источник: https://dmitripavlutin.com

Редакция: Команда webformyself.