ruby regex question

Hello

sorry I am ruby newbie. I want to ask a question on regex to extract values from a string and maybe types transformation is required.

for instance the string: "black berry 12".
I want go get the name: black berry [String]
the price: 12 [Int]

I did this in other language such as java/scala:

val regex = """(.+)\s+(\d+)""".r

val regex: scala.util.matching.Regex = (.+)\s+(\d+)

str match {

      > case regex(name,price) => (name,price.toInt)
      > }
val res2: (String, Int) = (black berry,12)

But sometimes for a simple task it's not convenient to write a java program.
so what's the ruby solution?

thanks

It's almost the same in Ruby. You can use the same regular expression. You
use the match method to match a string against a regular expression. And,
then you use the [] method to pick match elements by their 1-based-index (1
for name and 2 for price). Finally, the integer is converted from a String
to an Integer using the to_i method.

regex = /(.+)\s+(\d+)/
str = "black berry 12"
name = str.match(regex)[1]
price = str.match(regex)[2].to_i

Cheers!

···

On Fri, Apr 15, 2022 at 10:46 PM wilson <info@bigcount.xyz> wrote:

Hello

sorry I am ruby newbie. I want to ask a question on regex to extract
values from a string and maybe types transformation is required.

for instance the string: "black berry 12".
I want go get the name: black berry [String]
the price: 12 [Int]

I did this in other language such as java/scala:

> val regex = """(.+)\s+(\d+)""".r
val regex: scala.util.matching.Regex = (.+)\s+(\d+)

> str match {
      > case regex(name,price) => (name,price.toInt)
      > }
val res2: (String, Int) = (black berry,12)

But sometimes for a simple task it's not convenient to write a java
program.
so what's the ruby solution?

thanks

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<ruby-talk list: member options login page>

--
Andy Maleh

LinkedIn: https://www.linkedin.com/in/andymaleh
<https://www.linkedin.com/in/andymaleh>
Blog: http://andymaleh.blogspot.com
GitHub: AndyObtiva (Andy Maleh) · GitHub

Welcome to the wonderful world of Ruby! As is true with many things in Ruby, there is more than one way to achieve a desired result.

Here is one approach:

str.match(/"(.+)\s+(\d+)/)
puts "Name: #{$~[1]}"
puts "Price: #{$~[2]}"

#match (or any other regexp operator) populates the special variable $~, which is an array where element 0 contains the entire matched portion of the input, and elements 1..n contain the capture groups. This is often the best approach if you want to extract a number of fields from a single string.

Here is another approach:
  puts "Name: #{str[/(.+)\s+(\d+)/, 1]}"

str[regexp, pos] is equivalent to "str.match(regexp) ; $~[pos]" and is nicely expressive when you only have one capture group that you’re interested in.

IRB is your friend here — it provides a nice REPL environment where you can quickly see the effect of one or more lines of code.

Enjoy!

···

On Apr 15, 2022, at 7:45 PM, wilson <info@bigcount.xyz> wrote:

Hello

sorry I am ruby newbie. I want to ask a question on regex to extract values from a string and maybe types transformation is required.

for instance the string: "black berry 12".
I want go get the name: black berry [String]
the price: 12 [Int]

I did this in other language such as java/scala:

> val regex = """(.+)\s+(\d+)""".r
val regex: scala.util.matching.Regex = (.+)\s+(\d+)

> str match {
    > case regex(name,price) => (name,price.toInt)
    > }
val res2: (String, Int) = (black berry,12)

But sometimes for a simple task it's not convenient to write a java program.
so what's the ruby solution?

thanks

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<ruby-talk list: member options login page>

Hello

But sometimes for a simple task it's not convenient to write a java
program.
so what's the ruby solution?

when ruby, many (simple/surprising) solutions.

regex = %r<(.+)\s+(\d+)>

=> /(.+)\s+(\d+)/

str="black berry 12"

=> "black berry 12"

name, price = str.scan(regex).flatten

=> ["black berry", "12"]

price = price.to_i

=> 12

enjoy ruby!
just joining the fun here :slight_smile:

kind regards --botp

···

On Sat, Apr 16, 2022 at 10:46 AM wilson <info@bigcount.xyz> wrote:

Thanks for all your helps.

Jack Royal-Gordon wrote:

···

Here is one approach:

    str.match(/"(.+)\s+(\d+)/)
    puts "Name: #{$~[1]}"
    puts "Price: #{$~[2]}"

#match (or any other regexp operator) populates the special variable $~, which is an array where element 0 contains the entire matched portion of the input, and elements 1..n contain the capture groups. This is often the best approach if you want to extract a number of fields from a single string.

Here is another approach:
puts "Name: #{str[/(.+)\s+(\d+)/, 1]}"

str[regexp, pos] is equivalent to "str.match(regexp) ; $~[pos]" and is nicely expressive when you only have one capture group that you’re interested in.

Thanks robert.

I know your case.
for now i changed it to this, and it works.

irb(main):007:0> str =~ /(.+)\s+(\d+)/
=> 0
irb(main):008:0> puts "[" + $1 +"]"
[black berry ]
=> nil
irb(main):009:0> str =~ /(.+?)\s+(\d+)/
=> 0
irb(main):010:0> puts "[" + $1 +"]"
[black berry]
=> nil

Robert Klemme wrote:

···

$ ruby -e 'if /\A(.*?)\s+(\d+)\z/ =~ "black berry 12"; then puts $1, $2; end'

Hello

Another question,

can you tell me why the second and third regex usage looks quite similar but the order is reversed? which syntax is better among these three?

irb(main):011:0> fruits = ["black berry 12","cherry 9","kiwi peach 15"]
=> ["black berry 12", "cherry 9", "kiwi peach 15"]
irb(main):012:0>
irb(main):013:0> fruits.map {|s| s.match(/(.+?)\s+(\d+)/); [$~[1],$~[2]]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]
irb(main):014:0>
irb(main):015:0> fruits.map {|s| s =~ /(.+?)\s+(\d+)/; [$1,$2]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]
irb(main):016:0>
irb(main):017:0> fruits.map {|s| /(.+?)\s+(\d+)/ =~ s; [$1,$2]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]

Thanks

Robert Klemme wrote:

···

$ ruby -e 'if /\A(.*?)\s+(\d+)\z/ =~ "black berry 12"; then puts $1, $2; end'

If regexp goes first and there are named captures, then suddenly local variables are declared:

[2] pry(main)> fruits = ["black berry 12","cherry 9","kiwi peach 15"]
=> ["black berry 12", "cherry 9", "kiwi peach 15"]
[3] pry(main)> fruits.map {|s| /(?<fruit>.+?)\s+(?<num>\d+)/ =~ s; [fruit,num]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]
[4] pry(main)>

This is so that declared variables are always on the left, just as in: a = 5

···

On 4/16/22 08:29, wilson wrote:

Hello

Another question,

can you tell me why the second and third regex usage looks quite similar but the order is reversed? which syntax is better among these three?

irb(main):011:0> fruits = ["black berry 12","cherry 9","kiwi peach 15"]
=> ["black berry 12", "cherry 9", "kiwi peach 15"]
irb(main):012:0>
irb(main):013:0> fruits.map {|s| s.match(/(.+?)\s+(\d+)/); [$~[1],$~[2]]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]
irb(main):014:0>
irb(main):015:0> fruits.map {|s| s =~ /(.+?)\s+(\d+)/; [$1,$2]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]
irb(main):016:0>
irb(main):017:0> fruits.map {|s| /(.+?)\s+(\d+)/ =~ s; [$1,$2]}
=> [["black berry", "12"], ["cherry", "9"], ["kiwi peach", "15"]]