Regex замінить декілька пробілів одним простором


510

Подано рядок типу:

"У собаки довгий хвіст, і це ЧЕРВЕНО!"

Яку магію jQuery або JavaScript можна використовувати для збереження пробілів лише до одного максимуму простору?

Мета:

"У собаки довгий хвіст, і це ЧЕРВЕНО!"

4
Ви також хочете відповідати символам вкладки білого простору?
Кріс Фармер

@Chris, так, чудово, питання .... З усіма цими різними відповідями, як слід знати, яке найефективніше рішення?
AnApprentice

2
Усі внизу мають рацію, але це найбільш оптимізований вираз: str.replace(/ +(?= )/g,'');ви не замінюєте нічого, чого не потрібно.
Еван Керролл

2
Тут не буде помітної різниці в продуктивності. Ви завжди могли це профайлювати, але я сумніваюся, що це того варто. Я б пішов на найясніший.
Draemon

@EvanCarroll: Неправда - принаймні на Firefox. Ця версія працює значно повільніше. Дивіться результати профілювання у моїй відповіді (нижче).
Едвард Лопер

Відповіді:


937

З огляду на те, що ви також хочете охоплювати вкладки, нові рядки тощо, просто замініть \s\s+на ' ':

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

Якщо ви дійсно хочете охоплювати лише пробіли (і, отже, не вкладки, нові рядки тощо), зробіть це:

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

4
Вам також потрібно додати прапорець 'g' до регулярного виразу.
Рафаель

6
Це не працює, якщо потрібен порожній замість вкладки чи нового рядка. Правильно? / \ s + / працюватиме.
Фабіан

3
це може бути краще для вас як така функція, якfunction removeExtraSpaces(string){ return string.replace(/\s{2,}/g, ' ');}
Math chiller

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, виконуючи 100k замін рядків.

Я закликаю вас робити власні тести з профілювання з firebug, якщо ви вважаєте, що ефективність є проблемою. Люди, як відомо, погано прогнозують, де лежать вузькі місця в їхніх програмах.

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


5
jsperf.com/removing-multiple-spaces Ідіть і JSPerf! Останній метод; ( / +(?= )/g, ' ');виходить з ладу в IE9, він залишає подвійні пробіли: "Foo Bar Baz".replace(/ +(?= )/g, ' ');->"Foo Bar Baz"
Ненотлеп

як сильно різниться bw 1 і 2-й рядок
Vivek Panday

@VivekPanday - Я думаю, що це тому, що другий рядок замінює входження подвійних просторів єдиним пробілом, а перший замінює будь-який простір і пробілом. Чи цей час зберігається під час пошуку чи фактична заміна, я не знаю.
Малоріч

Це не видаляє початкові та кінцеві пробіли. Для цього дивіться цю відповідь .
Ітан

Відредаговано на замовлення, зменшуючи швидкість. Коментари Вівека та Малорика стосуються рядків з 380 мс і 790 мс.
Skippy le Grand Gourou

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

EDIT: Якщо ви хочете замінити всі види символів пробілу, найефективнішим способом буде такий:

str = str.replace(/\s{2,}/g,' ');

Смішно, що у вашій тестовій рядці немає навіть двох пробілів.
Джош Стодола

щойно зрозумів, що ви вже мали те, що я нещодавно придумав, +1 :)
meder omuraliev

2
Чомусь це не працює ... Багато "& nbsp;" відображаються ... Ймовірно, через CKEDITOR ...
AnApprentice

K виявляється, текст JQUERY () зіпсував речі. виправлено - дякую всім!
Підручник

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 символ кілька разів, і може бути менш ефективним, оскільки він націлений більше, ніж потрібно.

Я глибоко не перевіряв жодного з цих так lmk, якщо є помилки.

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

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'. І ось в чому справа, ви не хочете замінювати кожного символу пробілів f-en.
watain

Я згоден. Використовується для повнотекстового пошуку (і відображення фрагментів): Немає випадкових вкладок, невмикачів або thingjimajigs.
T4NK3R

13

У мене є цей метод, я називаю його методом Дерпа через відсутність кращого імені.

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

Запуск його в JSPerf дає деякі дивовижні результати.


2
Я буду збентежений як пекло, якщо виявиться, що я побив тестовий випадок, а не справді швидкий: D
Ненотлеп,

Надання тестового випадку ... Відмінна відповідь!
Ойтун

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) /", "Avenida Tancredo Neves, 745 Piso Térreo Sala");
Бруно Рібейро

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, ' ');

6

Ось альтернативне рішення, якщо ви не хочете використовувати заміну (замініть пробіли в рядку без використання 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 // The .replace (/ \ 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, " ");
}

:: НАЙКЛЮЧЕНО: Збережіть №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"/>

Це призведе до видалення спеціальних символів, дозволу для одинарних пробілів та видалення зайвих пробілів.


Що тут відбувається? Форматування виглядає дуже, дуже зламаним.
Ненотлеп


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 () видаляє порожні пробіли на початку та в кінці рядка, але не посередині рядка, тому в цьому випадку це не працює, вихід буде просто "My String with Multiple рядки ". api.jquery.com/jQuery.trim
egvaldes

1

заміна не використовується, string = string.split (/ \ W + /);



0

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

Додайте текст до тесту на скажіння файлу

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!"

Сподіваюся, це служить цілі


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

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

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"

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 touch pointer' .replace (/ ^ \ s + | \ s + $ | (\ s) + / g, "$ 1") має зробити трюк!


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));


врахуйте: console.log (testStr.split ("") .filter (s => s.length) .join (""))
dpjanes
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.