用于验证比率的正则表达式,例如Y39.29 / 28h

I am trying to write a regular expression which has to adhere the following rules:

Y120.001/100.232k
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
| | | | | | | | This k may be any letter, is not required
| | | | | | | Another number if there was a dot
| | | | | | A dot, not required
| | | | | A number with at least one digit, not required if a letter follows
| | | | Always a slash
| | | If there's a dot, digits can follow
| | A dot, not required
| A number, at least one digit
Always Y

These strings should work:

  • Y120.001/1k
  • Y1/h
  • Y2039/100
  • Y29/47.0

These should not work:

  • x203/493s (Not a Y at the start)
  • Y/39x (No number after the Y)
  • Y83839 (Second half missing)
  • Y78/29 (Last letter missing)

This is my early attempt, but it does not work in PHP:

/^\$*(\d)*(.*(\d))\/*(.*(\d))*.$

try this:

/Y\d+\.?\d*\/\d+\.?\d*\w?/

In javascript

re=/^Y\d+(\.\d+)?\/([a-z]$|\d+(\.\d+)?[a-z]?$)/

"Y120.001/1k Y1/h Y2039/100 Y29/47.0".split(" ").map(function(s) { return re.test(s) })
> [true, true, true, true]

"x203/493s Y/39x Y83839 Y78/29".split(" ").map(function(s) { return re.test(s) })
> [false, false, false, true]

This does accept Y78/29 as the trailing letter is optional.

This pattern should work:

^Y\d+(\.\d*)?/(\d+(\.\d*)?[a-z]?|[a-z])$

Demonstration

^Y\d+\.?\d*/((\d+\.?\d*)[a-zA-Z]?|(\d+\.?\d*)?[a-zA-Z])$

You can check the explanation of the regex from here.

After several iterations to correct for commented shortcomings:

/^Y\d+(?:\.\d+)?\/(?:(?:\d+(?:\.\d+)?)[A-Za-z]?|[A-Za-z])$/

Demonstration

Old Answer:

Here is a fully specific version that works well.

/^Y\d+(?:\.\d+)?\/(\d+(?:\.\d+)?)?[A-Za-z]?$/

Edited for a follow-up test in jsfiddle

If I understand the nuances of your specification

\bY\d+(?:\.\d*)?/(?:[A-Za-z]|(?:\d+(?:\.\d+)?[A-Za-z]?))\b

I understand your specification to include that if the first dot is present, the following number(s) is/are optional; but if the 2nd dot is present, there must be at least one following number. Others seem to have interpreted that part of your requirements differently.

this pattern should work Y[\d.]+\/[\d.]*[a-z]? Demo

What about the following one?

var r = /^Y\d+(\.\d+)?\/(\d+(\.\d+)?|(\d+(\.\d+)?)?[A-Za-z])$/;
console.log(true  === r.test('Y120.001/1k')); // true
console.log(true  === r.test('Y1/h'));        // true
console.log(true  === r.test('Y2039/100'));   // true
console.log(true  === r.test('Y29/47.0'));    // true
console.log(false === r.test('x203/493s'));   // true
console.log(false === r.test('Y/39x'));       // true
console.log(false === r.test('Y83839'));      // true