Regex, aby zastąpić wiele spacji jedną spacją

509

Biorąc pod uwagę ciąg znaków:

„Pies ma długi ogon i jest CZERWONY!”

Jakiego rodzaju magii jQuery lub JavaScript można użyć, aby spacje były ograniczone tylko do jednego spacji?

Cel:

„Pies ma długi ogon i jest CZERWONY!”
Uczeń
źródło
4
Czy chcesz także dopasować znaki tabulacji białych znaków?
Chris Farmer,
@Chris, Tak, świetne pytanie .... Skoro te wszystkie różne odpowiedzi, jak można wiedzieć, które jest najbardziej wydajnym rozwiązaniem?
AnApprentice
2
Wszyscy poniżej mają rację, ale jest to najbardziej zoptymalizowany regex: str.replace(/ +(?= )/g,'');nie zastępujesz niczego, czego nie musisz.
Evan Carroll,
2
Nie będzie zauważalnej różnicy w wydajności. Zawsze możesz go profilować, ale wątpię, czy byłoby warto. Wybrałbym najczystsze.
Draemon
@EvanCarroll: Nieprawda - przynajmniej w przeglądarce Firefox. Ta wersja działa znacznie wolniej. Zobacz wyniki profilowania w mojej odpowiedzi (poniżej).
Edward Loper,

Odpowiedzi:

936

Biorąc pod uwagę, że chcemy także kartami okładka, nowej linii, itp, po prostu zastąpić \s\s+z ' ':

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

Jeśli naprawdę chcesz objąć tylko spacje (a więc nie tabulatory, znaki nowej linii itp.), Zrób to:

string = string.replace(/  +/g, ' ');
BalusC
źródło
4
Musisz także dodać flagę „g” do wyrażenia regularnego.
Rafael
6
To nie działa, gdy potrzebne jest puste miejsce zamiast tabulacji lub nowego wiersza. Dobrze? / \ s + / będzie działać.
Fabian
3
byłoby lepiej dla ciebie jako funkcja, taka jakfunction removeExtraSpaces(string){ return string.replace(/\s{2,}/g, ' ');}
Chłodzenie matematyki
5
@Ethan: JS ma wbudowaną funkcję na to: trim(). Jest szybszy niż regex. Możesz po prostu zrobić string.trim().replace(/\s\s+/g, ' ');lub string.replace(/\s\s+/g, ' ').trim();.
BalusC
4
/\s\s+/gi /\s{2,}/gnie dopasowuj białych znaków, chyba że są co najmniej dwa sąsiadujące ze sobą, np. dopasuje \ t \ t, ale nie będzie pasować do pojedynczego \ t. string.replace(/\s+/g, ' ')dopasuje wszystkie pojedyncze i wielokrotne białe znaki podrzędne i zastąpi je pojedynczą spacją.
remyActual
159

Ponieważ wydajesz się być zainteresowany wydajnością, profilowałem je za pomocą firebuga. Oto wyniki, które otrzymałem:

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

To jest w Firefoksie, na którym działa 100 000 zamienników ciągu.

Zachęcam do wykonania własnych testów profilowania za pomocą firebuga, jeśli uważasz, że wydajność jest problemem. Ludzie notorycznie źle przewidują, gdzie leżą wąskie gardła w ich programach.

(Należy również pamiętać, że pasek narzędzi programisty IE 8 ma również wbudowany profiler - warto sprawdzić, jaka jest wydajność w IE.)

Edward Loper
źródło
5
jsperf.com/removing-multiple-spaces Śmiało i JSPerf! Ostatnia metoda; ( / +(?= )/g, ' ');kończy się niepowodzeniem w IE9, pozostawia podwójne spacje: "Foo Bar Baz".replace(/ +(?= )/g, ' ');->"Foo Bar Baz"
Nenotlep 26.04.13
ile jest różnic między 1 i 2 linią
Vivek Panday
@VivekPanday - Wyobrażam sobie, że dzieje się tak, ponieważ druga linia zastępuje tylko występowanie podwójnych spacji pojedynczą spacją, podczas gdy pierwsza zastępuje również każdą spację spacją. Czy to czas zaoszczędzony podczas wyszukiwania, czy faktycznej wymiany, nie wiem.
Maloric
To nie usuwa początkowych i końcowych białych znaków. W tym celu zobacz tę odpowiedź .
Ethan,
Edytowane na zamówienie przez zmniejszenie prędkości. Komentarze Viveka i Malorica odnoszą się do wierszy o długości 380 ms i 790 ms.
Skippy le Grand Gourou
43
var str = "The      dog        has a long tail,      and it is RED!";
str = str.replace(/ {2,}/g,' ');

EDYCJA: Jeśli chcesz zastąpić wszelkiego rodzaju białe znaki, najskuteczniejszym sposobem byłoby:

str = str.replace(/\s{2,}/g,' ');
watain
źródło
Zabawne, że w ciągu testowym nie ma nawet dwóch spacji.
Josh Stodola
właśnie zdałem sobie sprawę, że masz już to, co ostatnio wymyśliłem, +1 :)
meder omuraliev
2
Z jakiegoś powodu to nie działa ... Dużo „& nbsp;” pojawiają się ... Prawdopodobnie z powodu CKEDITOR ...
AnApprentice
K okazuje się, że tekst JQUERY () psuje rzeczy. naprawiono - dziękuję wszystkim!
AnApprentice
16

To jest jedno rozwiązanie, ale będzie kierowane na wszystkie znaki spacji:

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

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

Edycja : Prawdopodobnie jest to lepsze, ponieważ celuje w spację, po której następuje 1 lub więcej spacji:

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

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

Alternatywna metoda:

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

Sam z siebie nie korzystałem /\s+/, ponieważ zastępuje spacje, które obejmują 1 postać wiele razy i może być mniej wydajny, ponieważ celuje bardziej niż to konieczne.

Nie przetestowałem dogłębnie żadnego z nich, więc myślę, że są jakieś błędy.

Ponadto, jeśli zamierzasz zamienić ciąg znaków, pamiętaj o ponownym przypisaniu zmiennej / właściwości do własnego zastąpienia, np .:

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

Za pomocą jQuery.prototype.text:

var el = $('span:eq(0)');
el.text( el.text().replace(/\d+/, '') )
meder omuraliev
źródło
1
Pierwszy jest całkowicie bezcelowy, \ s \ s + oznacza, an po którym następuje jeden lub więcej \ s +, które można sprowadzić do jednego \ s +, drugi przykład jest bardziej dokładny, ponieważ chcemy zastąpić tylko podwójne spacje, a nie newlines, trzeci jest bardziej zoptymalizowany, ponieważ dotyczy tylko przykładów z ponad 2 spacjami. Ale str .replace (/ + (? =) / G, '') ;, dotyczy tylko przykładów z ponad 2 spacjami, ale oszczędza nadpisywanie spacji krokiem spacji.
Evan Carroll,
4
EvanCarroll kończy się niepowodzeniem, ponieważ \ s \ s + zdecydowanie różni się od \ s +. \ s \ s + pasuje do „\ t \ t” lub „\ t \ t \ t”, ale NIE do „\ t”. I o to w tym wszystkim chodzi, nie chcesz zastępować wszystkich pojedynczych białych znaków f-en.
oglądać
Ja robię. Służy do wyszukiwania pełnotekstowego (i wyświetlania fragmentów): Proszę nie losowych tabulatorów, nie przerywaczy ani innych rzeczy.
T4NK3R
13

Mam tę metodę, nazywam ją metodą Derpa z powodu braku lepszej nazwy.

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

Uruchomienie go w JSPerf daje zaskakujące wyniki.

Nenotlep
źródło
2
Będę zawstydzony jak diabli, jeśli okaże się, że sfałszowałem skrzynkę testową zamiast jej szybkiego działania: D
Nenotlep
Dostarczenie skrzynki testowej ... Doskonała odpowiedź!
Oytun
2
To sprawiło, że mój dzień :-) Zabawne, że „derping” często działa lepiej niż bycie „sprytnym”. Wydaje się jednak, że „Derp split” skopał mu tyłek. Mimo to zasługuje na głosowanie.
Fred Gandt,
13

Bardziej niezawodna metoda: zajmuje się także usuwaniem początkowych i końcowych spacji, jeśli istnieją. Na przykład:

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

W twoim przykładzie nie było tych spacji, ale są one również bardzo częstym scenariuszem, a przyjętą odpowiedzią było przycięcie ich do pojedynczych spacji, takich jak: „The ... RED!”, Co zwykle nie jest potrzebne.

Ethan
źródło
3
Użyłem tego wzorca na PHP i działa. $ parts = preg_split ("/ ^ \ s + | \ s + $ | \ s + (? = \ s) /", "Avenida Tancredo Neves, 745 Piso Térreo Sala");
Bruno Ribeiro,
11

Bardziej wytrzymałe:

funkcja przycinania (słowo)
{
    word = word.replace (/ [^ \ x21- \ x7E] + / g, ''); // zmień znaki niedrukowalne na spacje
    zwraca word.replace (/ ^ \ s + | \ s + $ / g, ''); // usuń spacje wiodące / końcowe
}
Chris
źródło
8

sugeruję

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

tylko dla spacji
LUB

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

do zamiany wielu zwrotów w pojedynczy zwrot również.

Leonard Meagher
źródło
6

Wiem, że jestem spóźniony na przyjęcie, ale znalazłem fajne rozwiązanie.

Oto on:

var myStr = myStr.replace(/[ ][ ]*/g, ' ');
ToXic73
źródło
6

Oto alternatywne rozwiązanie, jeśli nie chcesz używać zamiany (zamień spacje w ciągu bez użycia komendy 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);
imos
źródło
5

Kompleksowa nieszyfrowana odpowiedź dla początkujących i in.

To jest dla wszystkich manekinów, takich jak ja, które testują skrypty napisane przez niektórych z was, którzy nie działają.

Poniższe 3 przykłady to kroki, które podjąłem, aby usunąć znaki specjalne ORAZ dodatkowe spacje w następujących 3 witrynach (z których wszystkie działają idealnie) {1. EtaVisa.com 2. EtaStatus.com 3. Tikun.com}, więc wiem, że działają one doskonale.

Łączymy je razem z ponad 50 jednocześnie i NIE MA problemów.

// To usunęło znaki specjalne + 0-9 i dopuszcza tylko litery (wielkie i małe litery)

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

// To usunęło znaki specjalne i pozwala tylko na litery (wielkie i małe litery) oraz 0-9 i spacje

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

// To usunęło znaki specjalne i pozwala tylko na litery (wielkie i niższe) i 0-9 ORAZ spacje // .replace (/ \ s \ s + / g, "") na końcu usuwa nadmierne spacje // gdy I używane pojedyncze cudzysłowy, to nie działało.

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

:: NASTĘPNY :: Zapisz # 3 jako a .js// nazwałem mój NoDoubles.js

:: NASTĘPNY :: Dołącz swój JS do swojej strony

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

Uwzględnij to w polu formularza :: np

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

Tak to wygląda

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

To usunie znaki specjalne, pozwoli na pojedyncze spacje i usunie dodatkowe spacje.

PatFoster
źródło
Co tu się dzieje? Formatowanie wygląda bardzo, bardzo zepsute.
Nenotlep,
4

Również możliwość:

str.replace( /\s+/g, ' ' )
rfunduk
źródło
1
var string = "The dog      has a long   tail, and it     is RED!";
var replaced = string.replace(/ +/g, " ");

Lub jeśli chcesz również zastąpić karty:

var replaced = string.replace(/\s+/g, " ");
Brian Campbell
źródło
1
użycie + wydaje się czystsze, ale zastąpi również pojedyncze spacje pojedynczymi spacjami, trochę zbędnymi i nie jestem pewien, ale może to powodować problemy z wykonaniem przy znacznie dłuższym tekście.
ahmetunal
Zwykle używam najkrótszego, najprostszego rozwiązania, które będzie działać, i martwię się o tego rodzaju optymalizację, jeśli wiem, że muszę dopasować bardzo duży ciąg, w tym momencie faktycznie zmierzę różne rozwiązania, aby zobaczyć, które będą bądź szybszy. Trudno przewidzieć z góry, co będzie najszybsze bez testowania; na przykład w interpreterach JavaScript niektóre skomplikowane wyrażenia regularne spowodują przejście z szybkiej implementacji skompilowanej w JIT na wolno interpretowaną.
Brian Campbell
1

Jquery ma funkcję trim (), która w zasadzie zamienia coś takiego „FOo Bar” w „FOo Bar”.

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

Jest to o wiele bardziej przydatne, ponieważ automatycznie usuwa puste miejsca na początku i na końcu łańcucha. Nie wymaga wyrażenia regularnego.

Eryk Wróbel
źródło
3
Jak powiedziałeś, trim () usuwa puste spacje na początku i na końcu łańcucha, ale nie w środku łańcucha, więc nie działa w tym przypadku, wynikiem byłoby po prostu „Mój ciąg z wieloma linie". api.jquery.com/jQuery.trim
egvaldes
1

is replace nie jest używany, string = string.split (/ \ W + /);

Lin
źródło
0
var myregexp = new RegExp(/ {2,}/g);

str = str.replace(myregexp,' ');
Ahmetunal
źródło
0

Możemy użyć następującego wyrażenia regularnego objaśnionego za pomocą polecenia sed system. Podobne wyrażenie regularne może być używane w innych językach i platformach.

Dodaj tekst do pliku powiedz test

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

Możemy użyć następującego wyrażenia regularnego, aby zastąpić wszystkie białe spacje pojedynczym odstępem

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

Mam nadzieję, że to służy celowi

minhas23
źródło
0

Spróbuj zastąpić wiele spacji jedną spacją.

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

Czytaj więcej @ Zastępowanie wielu spacji pojedynczą spacją

jonathan klevin
źródło
0
var text = `xxx  df dfvdfv  df    
                     dfv`.split(/[\s,\t,\r,\n]+/).filter(x=>x).join(' ');

wynik:

"xxx df dfvdfv df dfv"
zestaw narzędzi
źródło
0

Aby uzyskać większą kontrolę, możesz użyć funkcji zwrotnej zastępowania do obsługi wartości.

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
źródło
0

Ten skrypt usuwa wszelkie spacje (wiele spacji, tabulatorów, zwrotów itp.) Między słowami i przycięciami:

// 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, ' ');
};
Oriol
źródło
0

„wskaźnik myszy dotyk” .replace (/ ^ \ s + | \ s + $ | (\ s) + / g, „$ 1”) powinno załatwić sprawę!

Ruwan Epage
źródło
0

Wiem, że musimy użyć wyrażenia regularnego, ale podczas wywiadu zostałem poproszony o zrobienie tego BEZ UŻYWANIA REGEX.

@slightlytyler pomógł mi przyjść z poniższym podejściem.

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
źródło
rozważyć: console.log (testStr.split ("") .filter (s => s.length) .join (""))
dpjanes