Podziel zdania za pomocą „” i usuń otaczające je spacje

84

Mam ten kod:

var r = /(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*){0,}$/
var s = "   a   ,  b  , c "
var m = s.match(r)
m => ["   a   ,  b  , c ", "a", "c"]

Wygląda na to, że dopasowano cały ciąg, ale gdzie się "b"podział? Wolałbym raczej oczekiwać:

["   a   ,  b  , c ", "a", "b", "c"]

dzięki czemu mogę zrobić m.shift()z wynikiem takim jak, s.split(',')ale także z usuniętymi białymi znakami.

Czy mam błąd w wyrażeniu regularnym, czy źle go zrozumiałem String.prototype.match?

meandre
źródło
Na marginesie {0,}to to samo, co *.
pimvdb
no cóż, smoże też być ' a, c'lub'a,b,c d e, f'
meandre
zmienię spacje na \ s
meandre

Odpowiedzi:

194

Oto całkiem prosty i prosty sposób na zrobienie tego bez konieczności stosowania złożonego wyrażenia regularnego.

var str = "   a   ,  b  , c "
var arr = str.split(",").map(function(item) {
  return item.trim();
});
//arr = ["a", "b", "c"]

Natywny .mapjest obsługiwany w IE9 i nowszych: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map


Lub w ES6 + robi się jeszcze krócej:

var arr = str.split(",").map(item => item.trim());

I na koniec, tutaj jest w Maszynie z wpisywanymi informacjami

var arr: string[] = str.split(",").map((item: string) => item.trim());
CBarr
źródło
4
Aby być wybrednym, możesz pozbyć się nawiasów klamrowych wokół argumentu mapy: var arr = str.split(",").map(item=>item.trim());
David Jones,
Jestem z @DavidJones w tej sprawie. Jeśli zmodyfikujesz swoją odpowiedź, byłoby świetnie. Bardzo mi pomogło w mojej sprawie, dziękuję wam!
Alreadytakenindeed
Tak, dobra uwaga - zaktualizowano odpowiedź, aby to odzwierciedlić! Ja osobiście zawsze dodaję nawiasy, ponieważ zwykle piszę Typescript i lubię podawać wyraźne informacje o typie, abyś zawsze mógł wiedzieć, co jest na pierwszy rzut oka.
CBarr
To świetna odpowiedź, Chris.
cyklicznie
Proste i najlepsze !!
Rahul Sonwanshi
23

Możesz to wypróbować bez skomplikowanych wyrażeń regularnych.

var arr = "   a   ,  b  , c ".trim().split(/\s*,\s*/);
console.log(arr);

xfg
źródło
17

Krótka odpowiedź: użyj m = s.match(/[^ ,]/g);


Twoje RE nie działa zgodnie z oczekiwaniami, ponieważ ostatnia grupa pasuje do ostatniego dopasowania (= c). Jeśli pominiesz {1,}$, zwrócone dopasowanie będzie " a , b ", "a", "b". Krótko mówiąc, wyrażenie RegExp zwraca tyle dopasowań, co określone grupy, chyba że użyjesz globalflagi /g. W tym przypadku zwrócona lista zawiera odwołania do wszystkich dopasowanych podciągów.

Aby osiągnąć swój efekt, użyj:

m = s.replace(/\s*(,|^|$)\s*/g, "$1");

To zastąpienie zastępuje każdy przecinek ( ,), początek ( ^) i koniec ( $), otoczony białą spacją, przez oryginalny znak ( commalub nic).

Jeśli chcesz uzyskać tablicę, użyj:

m = s.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/);

To RE przycina ciąg (usuwa wszystkie białe znaki na początku i na końcu, a następnie dzieli ciąg przez <any whitespace>,<any whitespace>. Zwróć uwagę, że znaki odstępu obejmują również znaki nowej linii i tabulatory. Jeśli chcesz trzymać się tylko spacji, użyj spacji ( ) zamiast \s.

Rob W
źródło
@ Andrew Rozszerzyłem wyjaśnienie dotyczące Twojego RE. Zobacz mój drugi przykład dla splitmetody.
Rob W
już opublikowałem to jako komentarz do innej odpowiedzi. zastanawiam się, czy mogę to zrobić za pomocą jednego wyrażenia regularnego i jednej operacji, czy też wyrażenie regularne js nie jest wystarczająco inteligentne?
meandre
@Andrew Tak, po prostu użyj s.match(/[^ ,]+/g). Jak wspomniałem na początku mojej odpowiedzi, /gjest to flaga globalna, która zwraca wszystkie pasujące podciągi.
Rob W
@Andrew: Jedna grupa przechwytywania tworzy jedno dopasowanie, niezależnie od liczby dodanych kwantyfikatorów. Jeśli chcesz dopasować a,b a ctrzeba trzy pary nawiasów (bez (?:...)):/(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)$/
user123444555621
@RobW, s.match (/ [^,] + / g) działa dokładnie tak, jak potrzebuję, dodaj to do swojej odpowiedzi
meandre
17

Skrót ES6:

str.split(',').map(item=>item.trim())
Dieter Gribnitz
źródło
9

Możesz to zrobić dla swoich celów
EDYCJA : Usuwanie drugiego zastąpienia zgodnie z sugestią w komentarzach. s.replace(/^\s*|\s*$/g,'').split(/\s*,\s*/)
Najpierw replaceprzycina ciąg, a następnie splitfunkcja dzieli '\s*,\s*'. To daje wynik["a", "b", "c"] na wejściu " a , b , c "

Jeśli chodzi o to, dlaczego Twoje wyrażenie regularne nie przechwytuje „b”, powtarzasz przechwyconą grupę, więc przechwytywane jest tylko ostatnie wystąpienie. Więcej na ten temat tutaj http://www.regular-expressions.info/captureall.html

Narendra Yadala
źródło
nie chcę wymazywać wszystkich białych znaków, tylko wokół przecinków lub na początku / końcu ciągu
meandre
@Andrew czy to nie wszystkie białe spacje? czy masz zdania, które chcesz podzielić?
David Hellsing
s.replace (/ ^ \ s * /, '') .replace (/ \ s * $ /, '') .split (/ \ s *, \ s * /) może to zrobić
meandre
@Andrew Zmieniono odpowiedź zgodnie z Twoimi wymaganiami.
Narendra Yadala
7

więc w końcu poszedłem z /(?=\S)[^,]+?(?=\s*(,|$))/g, co zapewnia dokładnie to, czego potrzebuję: wszystkie zdania podzielone przez „,” bez otaczających spacji.

'       a,    OMG     abc b a b, d o WTF        foo     '.
  match( /(?=\S)[^,]+?(?=\s*(,|$))/g )
=> ["a", "OMG     abc b a b", "d o WTF        foo"]

Wielkie dzięki!

meandre
źródło
tutaj jest znaczenie, jakie rozumiem. proszę poprawić mnie, jeśli nie mam racji: (?=\S)- zacznij przechwytywać tylko wtedy, gdy nie ma spacji z przodu [^,]+- przechwytuj jak najwięcej „nie-przecinków” ?- ale nie przechwytuj tego, co może zostać przechwycone przez następną grupę (?=\s*(,|$))- przechwyć wszystkie spacje wcześniej przecinek lub koniec łańcucha /g- powtórz przez cały ciąg
meandre
2

Jeśli chcesz nadal używać wyrażeń regularnych, zachowaj prosty kod i bez używania ES6:

s.replace(/ /g, '').split(",")

1 - Zastąp wszystkie spacje (/ / g) pustymi ciągami (``)

2 - Następnie podziel go na tablicę

Gotowe

AlbertSY
źródło
To najlepsza, najmniej skomplikowana odpowiedź.
Blazes