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
?
javascript
regex
meandre
źródło
źródło
{0,}
to to samo, co*
.s
może też być' a, c'
lub'a,b,c d e, f'
Odpowiedzi:
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
.map
jest obsługiwany w IE9 i nowszych: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/mapLub 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());
źródło
var arr = str.split(",").map(item=>item.trim());
Możesz to wypróbować bez skomplikowanych wyrażeń regularnych.
var arr = " a , b , c ".trim().split(/\s*,\s*/); console.log(arr);
źródło
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żyjeszglobal
flagi/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 (comma
lub 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
.źródło
split
metody.s.match(/[^ ,]+/g)
. Jak wspomniałem na początku mojej odpowiedzi,/g
jest to flaga globalna, która zwraca wszystkie pasujące podciągi.a
,b
ac
trzeba trzy pary nawiasów (bez(?:...)
):/(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)$/
Skrót ES6:
str.split(',').map(item=>item.trim())
źródło
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
replace
przycina ciąg, a następniesplit
funkcja 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
źródło
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!
źródło
(?=\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ągJeś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
źródło