Vadiya
Vadiya

Reputation: 111

Regex- to get part of String

I have got below string and I need to Get all the values Between Pizzahut: and |.

ABC:2fg45rdvsg|Pizzahut:j34532jdhgj|Dominos:3424232|Pizzahut:3242237|Wendys:3462783|Pizzahut:67688873rg|

I have got RegExpression .scan(/(?<=Pizzahut:)([.*\s\S]+)(?=\|)/) but it fetches

"j34532jdhgj|Dominos:3424232|Pizzahut:3242237|Wendys:3462783|Pizzahut:67688873rg|"

Result should be: 34532jdhgj,3242237,67688873rg

Upvotes: 2

Views: 175

Answers (2)

Tom Lord
Tom Lord

Reputation: 28305

I'm not sure why you're jumping to a regex solution here; that input string clearly looks structured to me, and you would probably do better by splitting it on the delimiters to convert it into a more convenient data structure.

Something like this:

input = "ABC:2fg45rdvsg|Pizzahut:j34532jdhgj|Dominos:3424232|Pizzahut:3242237|Wendys:3462783|Pizzahut:67688873rg"

converted_input = input
  .split('|') #=> ["ABC:2fg45rdvsg", "Pizzahut:j34532jdhgj", ... ]
  .map { |pair| pair.split(':') } #=> [["ABC", "2fg45rdvsg"], ["Pizzahut", "j34532jdhgj"], ... ]
  .group_by(&:first) #=> {"ABC"=>[["ABC", "2fg45rdvsg"]], "Pizzahut"=>[["Pizzahut", "j34532jdhgj"], ... ], "Dominos"=>[["Dominos", "3424232"]], ... ]
  .transform_values { |v| v.flat_map(&:last) }

(The above series of transformations is just one possible way; you could probably come up with a dozen similar alternative steps to convert this input into the same hash shown below! For example, by using reduce or even the CSV library.)

Which gives you the final result:

converted_input = {
  "ABC" => ["2fg45rdvsg"],
  "Pizzahut" => ["j34532jdhgj", "3242237", "67688873rg"],
  "Dominos" => ["3424232"],
  "Wendys" => ["3462783"]
}

Now that the data is formatted conveniently, obtaining data like your original request becomes trivial:

converted_input["Pizzahut"].join(',') #=> "j34532jdhgj,3242237,67688873rg"

(Although quite likely it would be more suitable to leave it as an Array, not a comma-separated String!!)

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627488

You can use

s='ABC:2fg45rdvsg|Pizzahut:j34532jdhgj|Dominos:3424232|Pizzahut:3242237|Wendys:3462783|Pizzahut:67688873rg|'
p s.scan(/Pizzahut:([^|]+)/).flatten
# => ["j34532jdhgj", "3242237", "67688873rg"]

See this Ruby demo and the Rubular demo.

It does not look possible that you have Pizzahut as a part of another word, but it is possible, use a version with a word boundary, /\bPizzahut:([^|]+)/.

The Pizzahut:([^|]+) matches Pizzahut: and then captures into Group 1 any one or more chars other than a pipe (with ([^|]+)).

Note that String#scan returns the captures only if a pattern contains a capturing group, so you do not need to use lookarounds.

Upvotes: 3

Related Questions