Я пытаюсь разобрать следующий вид строки:
[key:"val" key2:"val2"]
где есть произвольный ключ: пары "val" внутри. Я хочу получить имя ключа и значение. Для любопытных я пытаюсь разобрать формат базы задач воина.
Вот моя тестовая строка:
[description:"aoeu" uuid:"123sth"]
это означает, что в ключе или значении может быть что угодно, кроме пробелов, пробелов вокруг двоеточий нет, а значения всегда заключаются в двойные кавычки.
В узле это мой вывод:
[deuteronomy][gatlin][~]$ node
> var re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g
> re.exec('[description:"aoeu" uuid:"123sth"]');
[ '[description:"aoeu" uuid:"123sth"]',
'uuid',
'123sth',
index: 0,
input: '[description:"aoeu" uuid:"123sth"]' ]
Но description:"aoeu"
также соответствует этой модели. Как я могу вернуть все спички?
"some string".match(/regex/g)
Ответы:
Продолжайте вызывать
re.exec(s)
в цикле, чтобы получить все совпадения:Попробуйте это с этим JSFiddle: https://jsfiddle.net/7yS2V/
источник
while
вместоdo … while
?while(m = re.exec(s))
, что является анти-паттерном IMO, либо писатьm = re.exec(s); while (m) { ... m = re.exec(s); }
. Я предпочитаюdo ... if ... while
идиому, но другие методы тоже подойдут.g
флаг, иначе внутренний указатель не будет перемещен вперед. Docs .str.match(pattern)
, еслиpattern
имеет глобальный флагg
, вернет все совпадения в виде массива.Например:
источник
"All of us except @Emran:emran26, @Raju:raju13 and @Noman:noman42".match(/@(\w+):(\w+)/g)
(которые вернутся["@Emran:emran26", "@Raju:raju13", "@Noman:noman42"]
)/@\w/g
илиnew RegExp("@\\w", "g")
Чтобы просмотреть все совпадения, вы можете использовать
replace
функцию:источник
Это решение
Это основано на ответе Lawnsea, но короче.
Обратите внимание, что флаг `g 'должен быть установлен для перемещения внутреннего указателя вперед по вызовам.
источник
возвращает все совпадения в виде массива.
Если по какой-то таинственной причине вам нужна дополнительная информация
exec
, в качестве альтернативы предыдущим ответам, вы можете сделать это с помощью рекурсивной функции вместо цикла следующим образом (который также выглядит круче).как указывалось в комментариях ранее, важно иметь
g
в конце определения регулярного выражения перемещение указателя вперед при каждом выполнении.источник
Мы наконец начинаем видеть встроенную
matchAll
функцию, см. Здесь для описания и таблицы совместимости . Похоже, что по состоянию на май 2020 года поддерживаются Chrome, Edge, Firefox и Node.js (12+), но не IE, Safari и Opera. Похоже, что он был составлен в декабре 2018 года, поэтому дайте ему некоторое время, чтобы охватить все браузеры, но я верю, что он будет там.Встроенная
matchAll
функция хороша тем, что возвращает итерацию . Он также возвращает группы захвата для каждого матча! Так что вы можете делать такие вещи, какТакже кажется, что каждый объект соответствия использует тот же формат, что и
match()
. Таким образом , каждый объект представляет собой массив из спичечных и захвата групп, наряду с тремя дополнительными свойствамиindex
,input
иgroups
. Так это выглядит так:Для получения дополнительной информации о
matchAll
также есть страница разработчиков Google . Также доступны полифилы / прокладки .источник
Основано на функции Агуса, но я предпочитаю возвращать только значения совпадений:
источник
Итерации лучше:
Использование в цикле:
Или, если вы хотите массив:
источник
if (m)
должно бытьif (match)
matchAll
который возвращает итерацию : DЕсли у вас есть ES9
(Это означает, что ваша система: Chrome, Node.js, Firefox и т. Д. Поддерживает Ecmascript 2019 или более позднюю версию)
Используйте новую
yourString.matchAll( /your-regex/ )
.Если у вас нет ES9
Если у вас старая система, вот функция для простого копирования и вставки
пример использования:
выходы:
источник
Вот моя функция, чтобы получить совпадения:
источник
Начиная с ES9, теперь существует более простой и лучший способ получения всех совпадений вместе с информацией о группах захвата и их индексах:
В настоящее время поддерживается в Chrome, Firefox, Opera. В зависимости от того, когда вы читаете это, проверьте эту ссылку, чтобы увидеть ее текущую поддержку.
источник
g
и егоlastIndex
следует сбросить до 0 перед вызовомmatchAll
.Использовать это...
Он вернет массив всех совпадений ... Это будет работать нормально ... Но помните, что он не будет учитывать группы ... Он просто вернет полные совпадения ...
источник
Я бы определенно рекомендовал использовать функцию String.match () и создать для нее соответствующий RegEx. Мой пример со списком строк, который часто необходим при сканировании пользовательского ввода для ключевых слов и фраз.
Надеюсь это поможет!
источник
На самом деле это не поможет решить вашу более сложную проблему, но я все равно сообщу об этом, потому что это простое решение для людей, которые не выполняют глобальный поиск, как вы.
Я упростил регулярное выражение в ответе, чтобы он был более понятным (это не решение вашей конкретной проблемы).
Это выглядит более многословно, чем из-за комментариев, вот как это выглядит без комментариев
Обратите внимание, что любые группы, которые не совпадают, будут перечислены в массиве как
undefined
значения.Это решение использует оператор распространения ES6 для очистки массива определенных значений регулярных выражений. Вам нужно будет запустить свой код через Babel, если вы хотите поддержку IE11.
источник
Вот решение в одну строку без цикла while .
Порядок сохраняется в результирующем списке.
Потенциальные недостатки
источник
Я предполагаю, что если бы были крайние случаи, такие как дополнительные или пропущенные пробелы, это выражение с меньшими границами также могло бы быть вариантом:
Тест
RegEx Circuit
jex.im визуализирует регулярные выражения:
источник
Вот мой ответ:
источник
str
) имеет неправильный формат (слишком много жестких скобок). Вы только захватите ключ, а не значение. Ваш код имеет синтаксическую ошибку и не выполняется (последние скобки). Если вы отвечаете на «старый» вопрос уже полученным ответом, убедитесь, что вы добавили больше знаний и лучший ответ, чем уже принятый. Я не думаю, что ваш ответ делает это.