Чистое решение регулярных выражений немного не элегантно, потому что оно должно повторять захваты несколько раз, чтобы приспособить умножение и деление:
(?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, как действительные.
Конечно, вы можете изменить регулярное выражение, как требуется, например, используя *
в качестве символа умножения и т. д.