Regex для списку, розділеного комами


75

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

12365, 45236, 458, 1, 99996332, ......

Чи будуть коли-небудь втекли персонажі, такі як:12365,45236,"This is a \"test."
ceejayoz

7
Чому це повинен бути регулярний вираз? Залежно від мови, можливо, вам буде краще використовувати вбудований синтаксичний аналізатор CSV.
Марк Бік,

Відповіді:


112

Я пропоную вам зробити наступним чином:

(\d+)(,\s*\d+)*

який би працював для списку, що містить 1 або більше елементів.


1
ти маєш рацію, мені довелося позбавити першого символу, перш ніж я зміг використовувати регулярний вираз, дякую усім за допомогу
everLearningStudent

@ondrobaco: Ви, мабуть, перевіряєте лише першу групу матчів. Наступна група збігів буде містити решту списку.
Асаф,

4
вищевказане рішення не перевірить порожній список. (^$)|(^(\d+)(,\s*\d+)*$)може працювати, хоча.
Кріс

1
@Val: Проблема вашого рішення полягає в тому, що воно не буде відповідати спискам, у яких взагалі немає коми, наприклад "1"або "12345". Цей список не містить декількох елементів, тому в них немає коми. І ваш регулярний вираз (\d+,)*вимагає, щоб після кожного числа ставилася кома.
Асаф,

4
Як можна було б підібрати / витягти кожен елемент (із регулярним виразом)?
Густаво Пума,

19

Цей регулярний вираз витягує елемент зі списку, розділеного комами, незалежно від вмісту:

(.+?)(?:,|$)

Якщо ви просто заміните кому комусь іншим, він повинен працювати для будь-якого роздільника.


Чи витягує він більше одного елемента?
паранца

1
Щоб мати справу з пробілами після коми, як у OP, я пропоную цю невелику модифікацію: (.+?)(?:,\s*|$)
Чад Кломан,

1
@paranza - так, це витягне більше одного елемента, але лише якщо увімкнено глобальну відповідність, де будь-яка функція, яку ви використовуєте, повертає всі збіги замість лише першого. У минулі часи ви робили це, ставлячи "g" після косої риски (наприклад, /expr/g), але, мабуть, це не все так стандартно. Наприклад, у PHP вам потрібно використовувати preg_match_all()замість preg_match(). Інші смаки регулярного виразу мають інші способи зробити це.
Чад Кломан,

10

Це трохи залежить від ваших точних вимог. Я припускаю: всі числа, будь-яка довжина, числа не можуть мати початкових нулів, а також не містити коми або десяткові крапки. окремі числа, завжди розділені комою, а потім пробілом, а останнє число НЕ має коми і пробілу після нього. Будь-яка з цих помилок спрощує рішення.

([1-9] [0-9] *, []) * [1-9] [0-9] *

Ось як я це побудував подумки:

[0-9]  any digit.
[1-9][0-9]*  leading non-zero digit followed by any number of digits
[1-9][0-9]*, as above, followed by a comma
[1-9][0-9]*[ ]  as above, followed by a space
([1-9][0-9]*[ ])*  as above, repeated 0 or more times
([1-9][0-9]*[ ])*[1-9][0-9]*  as above, with a final number that doesn't have a comma.

Я знайшов цю відповідь дійсно корисною, мені просто знадобилося трохи налаштувати, щоб прийняти пробіли перед комою і після неї ([1-9][0-9]*[ ]*,[ ]*)*[1-9][0-9]*... можливо, комусь це буде корисно
pollirrata

Цей приклад мені найбільше подобається, як я дозволю розриви рядків після цього?
justinpees

7

Збіг повторюваних елементів, розділених комами:

(?<=,|^)([^,]*)(,\1)+(?=,|$)

Довідково .

Цей регулярний вираз можна використовувати для розділення значень списку, розділеного комами. Елементи списку можуть бути в лапках, без лапок або порожніми. Коми всередині пари лапок не збігаються.

,(?!(?<=(?:^|,)\s*"(?:[^"]|""|\\")*,)(?:[^"]|""|\\")*"\s*(?:,|$))

Довідково .


Що саме там робить символ труби (|)? Це єдиний символ, який не пояснено на сторінці, на яку ви посилаєтесь, і я не можу зрозуміти його.
Thomas Vander Stichele

@ThomasVanderStichele: Це для чергування. (foo|bar)відповідає fooабо bar. Для отримання додаткової інформації: regular-expressions.info/alternation.html
Амаль Муралі


5

Він відхилить сторонні коми у початку або в кінці рядка, якщо це для вас важливо.

((, )?(^)?(possible|value|patterns))*

Замініть possible|value|patternsрегулярним виразом, який відповідає дозволеним значенням.


2

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

^(([0-9a-zA-Z][0-9a-zA-Z_]*)([,][0-9a-zA-Z][0-9a-zA-Z_]*)*)$

1

Можливо, ви захочете вказати мову, щоб бути в безпеці, але

(\d+, ?)+(\d+)?

повинен працювати


1
Це рішення не вдається для списку, що містить лише 1 елемент. Дивіться моє рішення нижче.
Асаф,

1

У мене була трохи інша вимога, щоб проаналізувати закодований словник / хеш-таблицю з екранованими комами, наприклад:

"1=This is something, 2=This is something,,with an escaped comma, 3=This is something else"

Я думаю, що це елегантне рішення, з трюком, який дозволяє уникнути багатьох складних регулярних виразів:

if (string.IsNullOrEmpty(encodedValues))
{
    return null;
}
else
{
    var retVal = new Dictionary<int, string>();
    var reFields = new Regex(@"([0-9]+)\=(([A-Za-z0-9\s]|(,,))+),");
    foreach (Match match in reFields.Matches(encodedValues + ","))
    {
        var id = match.Groups[1].Value;
        var value = match.Groups[2].Value;
        retVal[int.Parse(id)] = value.Replace(",,", ",");
    }
    return retVal;
}

Я думаю, що його можна адаптувати до оригінального питання з виразом "подобається" @"([0-9]+),\s?"та розбирайте Groups[0].

Я сподіваюся, це комусь допоможе і дякую за поради щодо його наближення, особливо Асафу!


1

У JavaScript використовуйте, splitщоб допомогти, а також вловити будь-які від’ємні цифри:

'-1,2,-3'.match(/(-?\d+)(,\s*-?\d+)*/)[0].split(',');
// ["-1", "2", "-3"]
// may need trimming if digits are space-separated

0

Далі буде відповідати будь-якій комбінації слів, цифр / пробілів, розділених комами

(((.)*,)*)(.)*

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