Регулярное выражение для действительных единиц СИ (Международная система единиц) - PullRequest
2 голосов
/ 26 августа 2010

Я ищу регулярное выражение для проверки правильности ввода единиц СИ в форме http.Так, например,

kg/m^3

будет действительным для плотности или

m/s^2

для ускорения.

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

Ответы [ 3 ]

9 голосов
/ 26 августа 2010

Чистое решение регулярных выражений немного не элегантно, потому что оно должно повторять захваты несколько раз, чтобы приспособить умножение и деление:

(?x)
(    # Capture 1: the entire matched composed unit string
  (  # Capture 2: one unit including the optional prefix
    (Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)?  # Capture 3: optional prefix, taken from http://en.wikipedia.org/wiki/SI_prefix
    (m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|Ω|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L) # Capture 4: Base units and derived units w/o °C, rad and sr, but with L/l for litre
    (\^[+-]?[1-9]\d*)? # Capture 5: Optional power with optional sign. \^0 and \^-0 are not permitted
  |                 # or
    1               # one permitted, e.g. in 1/s
  )
  (?:    # Zero or more repetitions of one unit, plus the multiplication sign
     ·(  # Capture 6: one unit including the optional prefix
        (Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)?  # Capture 7
        (m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|Ω|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L) # Capture 8
        (\^[+-]?[1-9]\d*)? # Capture 9
      |                 # or
        1               # one permitted, e.g. in 1/s
      )
  )*
  (?:    # Optional: possibly multiplied units underneath a denominator sign
      \/(  # Capture 10
        (Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)?  # Capture 11
        (m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|Ω|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L) # Capture 12
        (\^[+-]?[1-9]\d*)? # Capture 13
      |                 # or
        1               # one permitted, e.g. in 1/s
      )
      (?:    # Zero or more repetitions of one unit, plus the multiplication sign
         ·(  # Capture 14
            (Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)?  # Capture 15
            (m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|Ω|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L) # Capture 16
            (\^[+-]?[1-9]\d*)? # Capture 17
          |                 # or
            1               # one permitted, e.g. in 1/s
          )
      )*
  )?
)

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

prefix = "(Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)"
unit = "(m|g|s|A|K|mol|cd|Hz|N|Pa|J|W|C|V|F|Ω|S|Wb|T|H|lm|lx|Bq|Gy|Sv|kat|l|L)"
power = "(\^[+-]?[1-9]\d*)"
unitAndPrefix = "(" + prefix + "?" + unit + power + "?" + "|1" + ")"
multiplied = unitAndPrefix + "(?:·" + unitAndPrefix + ")*"
withDenominator = multiplied + "(?:\/" + multiplied + ")?"

Регулярное выражение не выполняет никакой проверки непротиворечивости, конечно, оно также принимает такие вещи, как кг ^ -1 · кг ^ -1 · 1 / кг ^ -2, как действительные.

Конечно, вы можете изменить регулярное выражение, как требуется, например, используя * в качестве символа умножения и т. д.

1 голос
/ 26 августа 2010

Это связано RegEx для расстояния в метрической системе .Вам просто нужно расширить регулярное выражение для дополнительного знаменателя и показателя степени.

1 голос
/ 26 августа 2010

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

Вы можете, однако, сделать это для обычных типов, таких как те, которые вы дали.

Это рег. эксп. подойдет для ваших примеров, а также для этого (замените каждый \d+ на некоторое количество рег. для десятичных знаков, если хотите):

kg^2/m^3
kg*2/m
kg^2*2*m/m^3
kg/m/kg^3

(kg|m|s|A|K|cd|mol|\d+)((\*|\^)(kg|m|s|A|K|cd|mol|\d+))*(/(kg|m|s|A|K|cd|mol|\d+)((\*|\^)(kg|m|s|A|K|cd|mol|\d+))*)?

Но не что-то вроде:

kg^(kg/m)/m/kg^3

Единицы в питоне:

Преобразование единиц в Python

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...