Розділіть речення на ',' та видаліть навколишні пробіли


85

У мене є такий код:

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

Схоже, цілий рядок збігся, але куди "b"подівся? Я волію розраховувати отримати:

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

так що я можу робити m.shift()з результатом, подібним, s.split(',')але також із видаленими пробілами.

У мене є помилка в регулярному виразі чи я неправильно розумію String.prototype.match?


Як допоміжна нотатка {0,}- те саме, що *.
pimvdb

ну, sтакож може бути ' a, c'або'a,b,c d e, f'
meandre

я зміню пробіли на \ s
meandre

Відповіді:


195

Ось досить простий і зрозумілий спосіб зробити це, не потребуючи складного регулярного виразу.

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

Уродженець .mapпідтримується на IE9 і вище: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map


Або в ES6 + він стає ще коротшим:

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

І для завершення, ось він у Typescript із введеною інформацією

var arr: string[] = str.split(",").map((item: string) => item.trim());

4
Щоб бути прискіпливим, ви можете покінчити з фігурними дужками навколо аргументу карти: var arr = str.split(",").map(item=>item.trim());
Девід Джонс

Я з @DavidJones на цьому. Якщо ви зміните свою відповідь, було б чудово. Мені дуже допомогло у моїй справі, дякую, хлопці!
Вже прийнято

Так, хороший момент - відповідь оновлена, щоб відобразити це! Я особисто завжди додаю дужки, оскільки, як правило, я пишу Typescript, і я люблю надавати явну інформацію про тип, щоб ви завжди могли знати, що щось є з першого погляду.
CBarr

Це чудова відповідь Кріс.
циклічний

Просто і найкраще !!
Рахул Сонванші

24

Ви можете спробувати це без складних регулярних виразів.

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


17

Коротка відповідь: Використовуйте m = s.match(/[^ ,]/g);


Ваш RE працює не так, як очікувалося, оскільки остання група відповідає останньому (= c). Якщо ви пропустите {1,}$, повернутий матч буде " a , b ", "a", "b". Коротше кажучи, ваш RegExp повертає стільки збігів, скільки вказані групи, якщо ви не використовуєте globalпрапор /g. У цьому випадку у повернутому списку містяться посилання на всі відповідні підрядки.

Щоб досягти свого ефекту, використовуйте:

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

Ця заміна замінює кожну кому ( ,), початок ( ^) і кінець ( $), оточені пробілами, оригінальним символом ( commaабо нічим).

Якщо ви хочете отримати масив, використовуйте:

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

Цей RE обрізає рядок (видаляє всі пробіли на початку та в кінці, а потім розбиває рядок на <any whitespace>,<any whitespace>. Зверніть увагу, що пробіли також містять рядки та вкладки. Якщо ви хочете дотримуватися лише пробілів, використовуйте пробіл ( ) замість \s.


@Andrew Я розширив пояснення вашого RE. Див. Мій другий приклад щодо splitметоду.
Роб W

я вже опублікував це як коментар до іншої відповіді. цікаво, чи можу я це зробити за допомогою одного регулярного виразу і однієї операції, або js регулярний вираз недостатньо розумний?
meandre

@Andrew Так, просто використовуй s.match(/[^ ,]+/g). Як згадувалося вгорі моєї відповіді, /gце глобальний прапор, який повертає всі відповідні підрядки.
Роб W

@Andrew: Одна група зйомки створює одне збіг, незалежно від того, скільки кванторів ви додаєте. Якщо ви хочете зіставити a, bі c, вам потрібні три пари дужок (не враховуючи (?:...)):/(?:^\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)(?:,\s*([^\s]*)\s*)$/
user123444555621

@RobW, s.match (/ [^,] + / g) працює точно так, як мені потрібно, додайте його до своєї відповіді
meandre


9

Ви можете зробити це за своєю метою
РЕДАКТУВАТИ : Видалення другої заміни, як запропоновано в коментарях. s.replace(/^\s*|\s*$/g,'').split(/\s*,\s*/)
Спочатку replaceобрізає рядок, а потім splitфункція розбивається навколо '\s*,\s*'. Це дає вихід ["a", "b", "c"]на вхід " a , b , c "

Що стосується того, чому ваш регулярний вираз не фіксує "b", ви повторюєте захоплену групу, тому фіксується лише остання подія. Більше про це тут http://www.regular-expressions.info/captureall.html


я не хочу стирати всі пробіли, лише навколо коми або на початку / в кінці рядка
meandre

@Andrew хіба це не всі пробіли? чи у вас є речення, які ви хочете розділити?
Девід Хеллсінг,

s.replace (/ ^ \ s * /, '') .replace (/ \ s * $ /, '') .split (/ \ s *, \ s * /) може це зробити
meandre

@Andrew Змінив відповідь відповідно до ваших вимог.
Нарендра Ядала,

7

отже, нарешті, я пішов з /(?=\S)[^,]+?(?=\s*(,|$))/g, який надає саме те, що мені потрібно: усі речення розділені на ',' без пробілів.

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

дуже дякую!


ось сенс, наскільки я його розумію. будь ласка, виправте мене, якщо я не правий: (?=\S)- починайте захоплювати лише тоді, коли спереду немає пробілів [^,]+- фіксуйте якомога більше "не-коми" ?- але не фіксуйте те, що може бути захоплено наступною групою (?=\s*(,|$))- фіксуйте всі пробіли раніше кома або кінець рядка /g- повторити через весь рядок
meandre

2

Якщо ви хочете продовжувати використовувати регулярний вираз, тримайте код простим і без використання ES6:

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

1 - Замініть усі пробіли (/ / g) порожніми рядками ('')

2 - Потім розділіть його на масив

Et voila


Це найкраща, найменш складна відповідь.
Blazes
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.