Сделать регулярное выражение для всех физических / химических / биологических единиц?

php regex

96 просмотра

1 ответ

39 Репутация автора

Я пишу функцию PHP, чтобы соответствовать всем единицам в моем контенте. Например: у меня в первой фразе «25 NaHCO3, 25 D-глюкоза, 11,6 натрия, 7 MgSO4, 3,1 пируват натрия, 2,5 KCl, 1,25 NaH2PO4 и 0,5 CaCl2»

а также

«100 мг / кг, от 4 кГц до 48 кГц, 40 об / мин, 5 мин, 26 см, 95% ДИ, 16 лет, 1,910 Дж моль-1 К-1, 50 см3 мин-1» и многие другие.

Основная идея состоит в том, чтобы фиксировать все значения, идущие с любыми единицами измерения, в то же время оно не должно совпадать случайным образом «любые числа, сопровождаемые любыми словами» .

Я мог бы создать статическое регулярное выражение со всевозможными единицами в него, как

/((?<![\,\-\.\<\=\>\da-z])[\-\+]?\d+(?:[\.\,\/](?=\d)\d+%?)*%?)(?![\-])([\s\x{00A0}\-]*(?:[a-z]{2,}(?:\/?[a-z\-])*(?=[\s\,\.\;\)])|[a-z](?=[\.\,\;]?\s)|A m-[0-9]|C m-[0-9]|F m-1|Gy s-1|H m-1|J K-1( mol-1)?|J kg-1( K-1)?|k?J mol-1( K-1)?|J m-3|N m|N s|Pa|Pa s|V m-1|W|W m-1 K-1|W m-2|W m-2 sr-1|W sr-1|cd sr|mol s-1|kat m-3|kg m s-1|kg m2|kg m2 s-1|kg[\s\/]m-?2|kg m-3|kg\/kg|kg|ci|m[\/]s|m s-[0-9]|[cm]?m-?[0-9](?: (?:k?g|min)-?[0-9])?|mol m-?[0-9]?(?: s-?[0-9])?|rad(?: s-?[0-9])|sr|u\/c|[\x{00B0}\x{00BA}o][FC]|K|\x{00C5}))(?![a-z0-9])/ui

с помощью которого я мог бы захватить многие, но боль в том, что для этого мне нужно было добавить все единицы в мое регулярное выражение, и даже после добавления многих единиц я мог пропустить много единиц.

Есть ли другой вариант построить регулярное выражение с динамическим значением?

Автор: Jai Источник Размещён: 19.07.2016 08:39

Ответы (1)


2 плюса

38 Репутация автора

Решение

Первый шаг - разложить шаблон на подшаблоны, что особенно важно в вашем случае. Строительные блоки должны быть:

  • базовые единицы: J, K, с, мин, год, ...
  • список возможных префиксов: f, p, n, μ, m, c, d, D, k, M, G, T, P, ...
  • список символов, которые можно использовать для формирования производных единиц:., *, /, ^, (,), ...

Вот начало решения

юниты: (([PTGMkDdcmμnpf]?(mol|min|yrs|Hz|rpm|s|K|J|m|g)[\/\^\(\-\+\)0-9]*\s?)+)
юниты, которым предшествует только значение:[\+\-]?\d*\.?\d*e?[\+\-]?\d*\s?(([PTGMkDdcmμnpf]?(%|mol|min|yrs|Hz|rpm|s|K|J|m|g)[\/\^\(\-\+\)0-9]*\s?)+)

Первый должен анализировать только единицы, второй - единицы и значение, игнорируя числа, за которыми не следуют единицы и единицы, которым не предшествует значение.

И пример этого на работе на вашем примере . Я добавил еще несколько хитрых примеров, которые вам, возможно, придется учесть.

Однако имейте в виду, что это не проверяет целостность устройства.

Возможно, вы захотите взглянуть на то, как эта проблема была решена модулями GNU .

Он обеспечивает преобразование единиц и имеет очень обширный список единиц (включая валюты, американские системы и прочие единицы, которых я никогда не видел в других местах). В источнике есть файл "parse.y", который заботится о распознавании модуля.

Я полагаю, вы могли бы вдохновиться этим или по крайней мере извлечь выгоду из уже созданной базы данных единиц.

Обновление: спасибо Нахану Тагги за исправления. Вот также обновленная версия с еще более хитрыми примерами.

Автор: Alexis Prel Размещён: 17.06.2017 12:46
Вопросы из категории :
32x32