Reputation: 4802
I am looking for a regular expression regex
to match one of these patterns:
x
I don't know if match
is the correct method to achieve the results.
Matching examples:
' 30x '
'30x'
'20 30'
' 20 30 '
'30x'.match(regex).to_a #=> ['30']
'30 40'.match(regex).to_a #=> ['30', '40']
"30".match(regex).to_a # => ["30"]
" 30 ".match(regex).to_a # => ["30"]
"30 40".match(regex).to_a # => ["30", "40"]
Non-matching examples:
'20x 30 '
'x20 '
"30xx".match(regex).to_a # => nil
"30 a".match(regex).to_a # => nil
"30 60x".match(regex).to_a # => nil
"30x 20".match(regex).to_a # => nil
EDIT
Following @TeroTilus advice, this is the use case for this question:
The user will insert how he will pay an debt. Then, we've created a textfield to easily insert the payment condition. Example:
> "15 20" # Generate 2 bills: First for 15 days and second for 20 days
> "2x" # Generate 2 bills: First for 30 days and second for 60 days
> "2x 30" # Show message of 'Invalid Format'
> "ANY other string" # Show message of 'Invalid Format'
Upvotes: 0
Views: 382
Reputation: 1531
This should work for the examples you gave.
^(?:\s*(\d+))+x?\s*$
^ # Match start of string
(?: # Open non-capturing group
\s* # Zero or more spaces at start or between numbers
(\d+) # Capture one or more numbers
) # Close the group
+ # Group should appear one or more times
x? # The final group may have an x directly after it
\s* # Zero or more trailing spaces are allowed
$ # Match the end of the string
Edited to capture the numbers, not sure if you were looking to do this or just match the string.
Upvotes: 0
Reputation: 3437
I have newer written a single line of ruby so the syntax of the below might be horible
But, the easiest solution to your problem is; first reduce your first case to your second case, then do your matching for numbers.
Something like;
("20x 30".gsub/^\s*(\d+)x\s*$/,'\1').match(/\b\d+\b/)
Upvotes: 0
Reputation: 91518
How about:
/^\s*\d+(?:x\s*|\s*\d+)?$/
explanation:
The regular expression:
(?-imsx:^\s*\d+(?:x\s*|\s*\d+)?$)
matches as follows:
NODE EXPLANATION
----------------------------------------------------------------------
(?-imsx: group, but do not capture (case-sensitive)
(with ^ and $ matching normally) (with . not
matching \n) (matching whitespace and #
normally):
----------------------------------------------------------------------
^ the beginning of the string
----------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0 or
more times (matching the most amount
possible))
----------------------------------------------------------------------
\d+ digits (0-9) (1 or more times (matching
the most amount possible))
----------------------------------------------------------------------
(?: group, but do not capture (optional
(matching the most amount possible)):
----------------------------------------------------------------------
x 'x'
----------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0
or more times (matching the most amount
possible))
----------------------------------------------------------------------
| OR
----------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0
or more times (matching the most amount
possible))
----------------------------------------------------------------------
\d+ digits (0-9) (1 or more times (matching
the most amount possible))
----------------------------------------------------------------------
)? end of grouping
----------------------------------------------------------------------
$ before an optional \n, and the end of the
string
----------------------------------------------------------------------
) end of grouping
----------------------------------------------------------------------
Upvotes: 1
Reputation: 581
Try string.scan(/(^|\s+)(\d+)x?/).map(&:last)
, it probably does what you want.
Upvotes: 0