Regex для замены нескольких пробелов одним пробелом

511

Учитывая строку как:

"У собаки длинный хвост, и она КРАСНАЯ!"

Какую магию jQuery или JavaScript можно использовать, чтобы оставить только один пробел?

Цель:

"У собаки длинный хвост, и она КРАСНАЯ!"
AnApprentice
источник
4
Вы также хотите соответствовать символам табуляции белых пробелов?
Крис Фармер
@Chris, да, пожалуйста, отличный вопрос .... При всех этих разных ответах, как узнать, какое решение является наиболее эффективным?
AnApprentice
2
Все ниже правы, но это наиболее оптимизированное регулярное выражение: str.replace(/ +(?= )/g,'');вы не заменяете ничего, что вам не нужно.
Эван Кэрролл
2
Там не будет никакой заметной разницы в производительности. Вы всегда можете описать это, но я сомневаюсь, что это того стоит. Я бы пошел на самое ясное.
Draemon
@EvanCarroll: не соответствует действительности - по крайней мере, в Firefox. Эта версия работает значительно медленнее. Смотрите результаты профилирования в моем ответе (ниже).
Эдвард Лопер

Ответы:

937

Учитывая, что вы также хотите охватить вкладки, новые строки и т. Д., Просто замените \s\s+на ' ':

string = string.replace(/\s\s+/g, ' ');

Если вы действительно хотите охватить только пробелы (и, следовательно, не табуляции, переносы и т. Д.), Сделайте так:

string = string.replace(/  +/g, ' ');
BalusC
источник
4
Вам также необходимо добавить флаг 'g' в регулярное выражение.
Рафаэль
6
Это не работает, когда требуется пробел вместо вкладки или новой строки. Правильно? / \ s + / будет работать.
Фабиан
3
это может быть лучше для вас, как функция, такая какfunction removeExtraSpaces(string){ return string.replace(/\s{2,}/g, ' ');}
Математический чиллер
5
@Ethan: JS имеет функцию встроенной для этого: trim(). Это быстрее, чем регулярное выражение. Вы могли бы просто сделать string.trim().replace(/\s\s+/g, ' ');или string.replace(/\s\s+/g, ' ').trim();.
BalusC
4
/\s\s+/gи /\s{2,}/gне совпадают с пробельными символами, если между ними нет по крайней мере двух, например, будет соответствовать \ t \ t, но не будет совпадать с одним \ t. string.replace(/\s+/g, ' ')будет соответствовать всем одиночным и множественным подстрокам пробельных символов и заменяться одним пробелом.
remyActual
159

Поскольку вы, кажется, заинтересованы в производительности, я описал их с помощью firebug. Вот результаты, которые я получил:

str.replace( /  +/g, ' ' )       ->  380ms
str.replace( /\s\s+/g, ' ' )     ->  390ms
str.replace( / {2,}/g, ' ' )     ->  470ms
str.replace( / +/g, ' ' )        ->  790ms
str.replace( / +(?= )/g, ' ')    -> 3250ms

Это на Firefox, на котором выполняется 100 000 замен строк.

Я рекомендую вам сделать свои собственные тесты профилирования с Firebug, если вы считаете, что производительность является проблемой. Люди, как известно, плохо предсказывают, где находятся узкие места в их программах.

(Также обратите внимание, что в панель инструментов разработчика IE 8 также встроен профилировщик - возможно, стоит проверить, какова производительность в IE.)

Эдвард Лопер
источник
5
jsperf.com/removing-multiple-spaces Вперед и JSPerf! Последний метод; ( / +(?= )/g, ' ');терпит неудачу в IE9, он оставляет двойные пробелы: "Foo Bar Baz".replace(/ +(?= )/g, ' ');->"Foo Bar Baz"
Nenotlep
сколько различий между 1 и 2-й строкой
Vivek Panday
@VivekPanday - я предполагаю, что это потому, что вторая строка заменяет только вхождения двойных пробелов одним пробелом, а первая заменяет также любой пробел пробелом. Это время сэкономлено во время поиска или замены, я не знаю.
Малорик
Это не удаляет начальные и конечные пробелы. Для этого смотрите этот ответ .
Итан
Отредактировано на заказ по убыванию скорости. Комментарии Вивека и Малорика относятся к строкам с 380 мс и 790 мс.
Скиппи ле Гран Гуру
43
var str = "The      dog        has a long tail,      and it is RED!";
str = str.replace(/ {2,}/g,' ');

РЕДАКТИРОВАТЬ: Если вы хотите заменить все виды пробельных символов, наиболее эффективный способ будет следующим:

str = str.replace(/\s{2,}/g,' ');
WATAIN
источник
Забавно, что в вашей тестовой строке нет даже двух пробелов.
Джош Стодола
только что понял, что у тебя уже есть то, что я недавно придумал, +1 :)
meder omuraliev
2
По какой-то причине это не работает ... Много "& nbsp;" появляются ... Вероятно, из-за CKEDITOR ...
AnApprentice
K оказывается, что текст JQUERY () все испортил. исправлено - спасибо всем!
AnApprentice
16

Это одно решение, хотя оно будет нацелено на все пробелы:

"The      dog        has a long tail,      and it is RED!".replace(/\s\s+/g, ' ')

"The dog has a long tail, and it is RED!"

Редактировать : это, вероятно, лучше, так как это предназначается для пробела, сопровождаемого 1 или больше пробелов:

"The      dog        has a long tail,      and it is RED!".replace(/  +/g, ' ')

"The dog has a long tail, and it is RED!"

Альтернативный метод:

"The      dog        has a long tail,      and it is RED!".replace(/ {2,}/g, ' ')
"The dog has a long tail, and it is RED!"

Я не использовал /\s+/сам по себе, поскольку он заменяет пробелы, которые занимают 1 символ, несколько раз и может быть менее эффективным, поскольку он нацелен больше, чем необходимо.

Я не проверял глубоко ни один из них, так что, если есть ошибки.

Кроме того, если вы собираетесь выполнять замену строк, не забудьте переназначить переменную / свойство для его собственной замены, например:

var string = 'foo'
string = string.replace('foo', '')

Используя jQuery.prototype.text:

var el = $('span:eq(0)');
el.text( el.text().replace(/\d+/, '') )
медер омуралиев
источник
1
Первый из них абсолютно бессмысленный, \ s \ s + означает, что за \ s следует один или несколько \ s +, что можно уменьшить до одного \ s +, второй пример более точный, потому что мы хотим заменить только двойные пробелы, а не новая строка, третья более оптимизирована, поскольку она применяется только к примерам с пробелами 2+. Но str.replace (/ + (? =) / G, '') ;, применяется только к примерам с пробелами 2+, но сохраняет перезапись пробела с шагом пробела.
Эван Кэрролл
4
EvanCarroll вы провалили, потому что \ s \ s + определенно отличается от \ s +. \ s \ s + будет соответствовать '\ t \ t' или '\ t \ t \ t', но НЕ '\ t'. И это все, что вам нужно, вы не хотите заменять каждый символ пробела.
Watain
Я делаю. Используется для полнотекстового поиска (и отображения фрагмента): пожалуйста, никаких случайных вкладок, неразрывных элементов или штуковин.
T4NK3R
13

У меня есть этот метод, я называю его методом Derp из-за отсутствия лучшего имени.

while (str.indexOf("  ") !== -1) {
    str = str.replace(/  /g, " ");
}

Запуск его в JSPerf дает удивительные результаты.

Nenotlep
источник
2
Я буду смущен до чертиков, если окажется, что я выдумал тестовый пример вместо того, чтобы он был на самом деле быстрым: D
Nenotlep
Предоставление теста ... Отличный ответ!
Ойтун
2
Это сделало мой день :-) Забавным, как часто «сумасшедший» работает лучше, чем «умный». «Сумасшедший раскол», похоже, надрал ему задницу. Тем не менее, заслуживает голосования.
Фред Гандт
13

Более надежный метод: Это заботится также удаление начальных и конечных пробелов, если они существуют. Например:

// NOTE the possible initial and trailing spaces
var str = "  The dog      has a long   tail, and it     is RED!  "

str = str.replace(/^\s+|\s+$|\s+(?=\s)/g, "");

// str -> "The dog has a long tail, and it is RED !"

В вашем примере не было этих пробелов, но они также являются очень распространенным сценарием, и принятый ответ заключался только в том, чтобы обрезать их в отдельные пробелы, например: «... КРАСНЫЙ!», А это не то, что вам обычно нужно.

Итан
источник
3
Я использовал этот шаблон на PHP и работает. $ parts = preg_split ("/ ^ \ s + | \ s + $ | \ s + (? = \ s) /", "Авенида Танкредо Невес, 745 Писо Террео Сала");
Бруно Рибейро
11

Более надежный:

функция обрезки (слово)
{
    word = word.replace (/ [^ \ x21- \ x7E] + / g, ''); // изменить непечатаемые символы на пробелы
    вернуть word.replace (/ ^ \ s + | \ s + $ / g, ''); // удаляем начальные / конечные пробелы
}
Крис
источник
8

Я предлагаю

string = string.replace(/ +/g," ");

для всего пространства
ИЛИ

string = string.replace(/(\s)+/g,"$1");

для преобразования нескольких возвратов в одно возвращение также.

Леонард Мигер
источник
6

Я знаю, что опаздываю на вечеринку, но нашел хорошее решение.

Вот:

var myStr = myStr.replace(/[ ][ ]*/g, ' ');
ToXic73
источник
6

Вот альтернативное решение, если вы не хотите использовать replace (заменяйте пробелы в строке без использования replace javascript)

var str="The dog      has a long   tail, and it     is RED!";
var rule=/\s{1,}/g;
str = str.split(rule).join(" "); 
document.write(str);
ИМОС
источник
5

Комплексный незашифрованный ответ для новичков и соавт.

Это для всех чайников, как я, которые тестируют сценарии, написанные некоторыми из вас, ребята, которые не работают.

Следующие 3 примера - это шаги, которые я предпринял для удаления специальных символов И лишних пробелов на следующих 3 веб-сайтах (все из которых работают отлично) {1. EtaVisa.com 2. EtaStatus.com 3. Tikun.com} так что я знаю, что они работают отлично.

Мы связали их вместе более чем с 50 за один раз и никаких проблем.

// Это удалило специальные символы + 0-9 и позволяет использовать только буквы (верхний и нижний регистр)

function NoDoublesPls1()
{
var str=document.getElementById("NoDoubles1");
var regex=/[^a-z]/gi;
str.value=str.value.replace(regex ,"");
}

// Это удаляет специальные символы и позволяет использовать только буквы (верхний и нижний регистр) и 0-9 пробелы AND

function NoDoublesPls2()
{
var str=document.getElementById("NoDoubles2");
var regex=/[^a-z 0-9]/gi;
str.value=str.value.replace(regex ,"");
}

// Это удаляет специальные символы и позволяет использовать только буквы (верхний и нижний регистр) и пробелы 0-9 и AND. // Место (/ \ s \ s + / g, "") в конце удаляет лишние пробелы // когда я использовал одинарные кавычки, это не сработало.

function NoDoublesPls3()
{    var str=document.getElementById("NoDoubles3");
var regex=/[^a-z 0-9]/gi;
str.value=str.value.replace(regex ,"") .replace(/\s\s+/g, " ");
}

:: NEXT :: Сохранить # 3 как a .js// Я назвал мой NoDoubles.js

:: ДАЛЕЕ :: Включите свой JS на свою страницу

 <script language="JavaScript" src="js/NoDoubles.js"></script>

Включите это в поле формы: например,

<INPUT type="text" name="Name"
     onKeyUp="NoDoublesPls3()" onKeyDown="NoDoublesPls3()" id="NoDoubles3"/>

Чтобы это выглядело так

<INPUT type="text" name="Name" onKeyUp="NoDoublesPls3()" onKeyDown="NoDoublesPls3()" id="NoDoubles3"/>

Это удалит специальные символы, оставит одинарные пробелы и удалит лишние пробелы.

PatFoster
источник
Что здесь происходит? Форматирование выглядит очень, очень нарушено.
Ненотлеп
4

Также есть возможность:

str.replace( /\s+/g, ' ' )
rfunduk
источник
1
var string = "The dog      has a long   tail, and it     is RED!";
var replaced = string.replace(/ +/g, " ");

Или, если вы также хотите заменить вкладки:

var replaced = string.replace(/\s+/g, " ");
Брайан Кэмпбелл
источник
1
использование + кажется более чистым, но оно также заменит одиночные пробелы одиночными пробелами, немного излишними, и я не уверен, но это может создать проблемы производительности с намного более длинным текстом.
Ахметунал
Я склонен использовать самое короткое и простое решение, которое будет работать, и беспокоиться об оптимизации такого рода только в том случае, если я знаю, что мне нужно сопоставить очень большую строку, и в этот момент я на самом деле буду измерять различные решения, чтобы увидеть, какие из них будут будь быстрее Может быть трудно заранее предсказать, что будет быстрее без тестирования; например, в интерпретаторах JavaScript некоторые сложные регулярные выражения заставят вас перейти от быстрой JIT-скомпилированной реализации к медленной интерпретируемой.
Брайан Кэмпбелл
1

Jquery имеет функцию trim (), которая в основном превращает что-то вроде этого «FOo Bar» в «FOo Bar».

var string = "  My     String with  Multiple lines    ";
string.trim(); // output "My String with Multiple lines"

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

Эрик Врубель
источник
3
Как вы сказали, trim () удаляет пустые пробелы в начале и в конце строки, но не в середине строки, поэтому в этом случае это не работает, вывод будет просто «Моя строка с несколькими» линии». api.jquery.com/jQuery.trim
egvaldes
1

is replace не используется, string = string.split (/ \ W + /);

Lin
источник
0
var myregexp = new RegExp(/ {2,}/g);

str = str.replace(myregexp,' ');
ahmetunal
источник
0

Мы можем использовать следующее регулярное выражение, объясненное с помощью системной команды sed. Подобное регулярное выражение может использоваться на других языках и платформах.

Добавьте текст в какой-нибудь файл скажем test

manjeet-laptop:Desktop manjeet$ cat test
"The dog      has a long   tail, and it     is RED!"

Мы можем использовать следующее регулярное выражение для замены всех пробелов одним пробелом

manjeet-laptop:Desktop manjeet$ sed 's/ \{1,\}/ /g' test
"The dog has a long tail, and it is RED!"

Надеюсь, что это служит цели

minhas23
источник
0

Попробуйте заменить несколько пробелов одним пробелом.

<script type="text/javascript">
    var myStr = "The dog      has a long   tail, and it     is RED!";
    alert(myStr);  // Output 'The dog      has a long   tail, and it     is RED!'

    var newStr = myStr.replace(/  +/g, ' ');
    alert(newStr);  // Output 'The dog has a long tail, and it is RED!'
</script>

Читать далее @ Замена нескольких пробелов одним пробелом

Джонатан Клевин
источник
0
var text = `xxx  df dfvdfv  df    
                     dfv`.split(/[\s,\t,\r,\n]+/).filter(x=>x).join(' ');

результат:

"xxx df dfvdfv df dfv"
Инструментарий
источник
0

Для большего контроля вы можете использовать обратный вызов замены для обработки значения.

value = "tags:HUNT  tags:HUNT         tags:HUNT  tags:HUNT"
value.replace(new RegExp(`(?:\\s+)(?:tags)`, 'g'), $1 => ` ${$1.trim()}`)
//"tags:HUNT tags:HUNT tags:HUNT tags:HUNT"
jackotonye
источник
0

Этот скрипт удаляет любые пробелы (несколько пробелов, табуляции, возвратов и т. Д.) Между словами и пробелами:

// Trims & replaces any wihtespacing to single space between words
String.prototype.clearExtraSpace = function(){
  var _trimLeft  = /^\s+/,
      _trimRight = /\s+$/,
      _multiple  = /\s+/g;

  return this.replace(_trimLeft, '').replace(_trimRight, '').replace(_multiple, ' ');
};
Ориоль
источник
0

'touch указатель мыши' .replace (/ ^ \ s + | \ s + $ | (\ s) + / g, "$ 1") должно сработать!

Ruwan Epage
источник
0

Я знаю, что мы должны использовать регулярные выражения, но во время интервью меня попросили сделать БЕЗ ИСПОЛЬЗОВАНИЯ REGEX.

@slightlytyler помог мне перейти на следующий подход.

const testStr = "I   LOVE    STACKOVERFLOW   LOL";

const removeSpaces = str  => {
  const chars = str.split('');
  const nextChars = chars.reduce(
    (acc, c) => {
      if (c === ' ') {
        const lastChar = acc[acc.length - 1];
        if (lastChar === ' ') {
          return acc;
        }
      }
      return [...acc, c];
    },
    [],
  );
  const nextStr = nextChars.join('');
  return nextStr
};

console.log(removeSpaces(testStr));

xSachinx
источник
рассмотрим: console.log (testStr.split ("") .filter (s => s.length) .join (""))
dpjanes