Reputation: 93
I need to split a string containing variables/delimiters, something like;
"Hello %Customer Name% your order number is %Order Number% and will be delivered soon"
Using;
string.split(/%/)
=> ["Hello ", "Customer Name", " your order number is ", "Order Number", " and will be delivered soon"]
Which is close to the requirement, but I'm trying to get to;
["Hello ", "%Customer Name%", " your order number is ", "%Order Number%", " and will be delivered soon"]
So essentially I need to split at % but keep it within the returned fields. I've tried a look ahead/behind with regex but cannot get it quite right.
Upvotes: 3
Views: 156
Reputation: 110665
Here are three ways that could be done.
str = "%Hello% dear %Cust Name% %your order %Order Nbr% was %lost%"
1. Use String#split
r = /
(?<= # begin positive lookbehind
\A # match beginning of string
| # or
[ ] # match a space
) # end positive lookbehind
(?=%) # positive lookahead asserts next char is '%'
| # or
(?<=%) # positive lookbehind asserts previous char is '%'
(?= # begin a positive lookahead
[ ] # match a space
| # or
\z # match end of string
) # end positive lookahead
/x # free-spacing regex definition mode
str.split r
#=> ["%Hello%", " dear ", "%Cust Name%", " ", "%your%", " order ",
# "%Order Nbr%", " was ", "%lost%"]
2. Use String#scan
r = /
%[^%]*% # match '%', 0+ chars other than '%', '%'
| # or
(?: # begin non-capture group#
(?<=\A) # positive lookbehind asserts at beginning of string
| # or
(?<=%) # positive lookbehind asserts previous char is '%'
(?=[ ]) # positive lookahead asserts next char is a space
) # end non-capture group
[^%]* # match 0+ chars other than '%'
(?= # begin positive lookahead
\z # match end of string
| # or
(?<=[ ]) # assert previous char is a space
% # match '%'
) # end positive lookahead
/x # free-spacing regex definition mode
str.scan r
#=> ["%Hello%", " dear ", "%Cust Name%", " ", "%your%", " order ",
# "%Order Nbr%", " was ", "%lost%"]
3. Use Enumerable#slice_when
str.each_char.slice_when { |a,b|
(a == ' ') & (b == '%') || (a == '%') & (b == ' ') }.map(&:join)
#=> ["%Hello%", " dear ", "%Cust Name%", " ", "%your%", " order ",
# "%Order Nbr%", " was ", "%lost%"]
Upvotes: 0
Reputation: 626689
You may use String#split
with a pattern like
/(%[^%]*%)/
According to the documentation:
If pattern contains groups, the respective matches will be returned in the array as well.
See the regex demo, it matches and captures into Group 1 a %
char, then any 0 or more chars other than %
, and then a %
.
See a Ruby demo:
s = "Hello %Customer Name% your order number is %Order Number% and will be delivered soon"
p s.split(/(%[^%]*%)/)
# => ["Hello ", "%Customer Name%", " your order number is ", "%Order Number%", " and will be delivered soon"]
Upvotes: 1