0

I am trying to write a method to pulls out every string that matches the criteria from a large text file:

  • Every element is separated by a comma
  • The first 5 elements could be any number from 1-59
  • The next 21 elements should be numbers from 1-5
  • The next 27 elements could be either true or false (no caps)
  • The final 5 elements are integers from 1-5

My code:

#this string should be returned by the regex matching
str="3,15,14,31,40,5,5,4,5,3,4,4,5,2,2,2,1,2,1,1,3,3,3,2,4,3,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,3,3,3,2,3"
matchResult=/[1-59]{5}[1-5]{21}[true|false]{27}[1-5]{5}/.match(str)
matchResult.each{|x| #this doesnt work....why?
    puts x
}
  • What is the correct way to print all matches? matchResult.each throws an error. I thought it returned an array of matches.
  • How can I adjust my regex to expect a comma between every value (not at the ends of the string)?

2 Answers 2

1

Put true or false inside a capturing group or non-capturing group like (?:true|false) so that it would match the exact true or false substring , this [true|false] will match a single character only whether it may be t or r or u or e or | ,....

> str="3,15,14,31,40,5,5,4,5,3,4,4,5,2,2,2,1,2,1,1,3,3,3,2,4,3,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,3,3,3,2,3"
> str.match(/^(?:[1-5]\d|[1-9])(?:,(?:[1-5]\d|[1-9])){4}(?:,[1-5]){21}(?:,(?:true|false)){27}(?:,[1-5]){5}$/)
=> #<MatchData "3,15,14,31,40,5,5,4,5,3,4,4,5,2,2,2,1,2,1,1,3,3,3,2,4,3,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,3,3,3,2,3">
Sign up to request clarification or add additional context in comments.

3 Comments

some of my strings might have a comma at the beginning. Is there a way to adjust the regex for that? I tried: (/^(?:[,]*)(?:[1-5]\d|[1-9])(?:,(?:[1-5]\d|[1-9])){4}(?:,[1-5]){21}(?:,(?:true|false)){27}(?:,[1-5]){5}$/) but that didnt work
how your string looks like?
str=",3,15,14,31,40,5,5,4,5,3,4,4,5,2,2,2,1,2,1,1,3,3,3,2,4,3,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,3,3,3,2,3"
1

In regards to your first question:

"What is the correct way to print all matches? matchResult.each throws an error. I thought it returned an array of matches."

The Regex .match method doesn't return an array of matches; it returns either a match object (in this case, a string, since you're calling .match on a string) or nil if there are no matches (see docs here).

This means matchResult is a string, and you can't call .each on a string, which is why you're getting an error message. See this post for more info on .each & strings.

2 Comments

Thanks, you pointed me in the right direction. It turns out I had to use scan rather then match
No problem, glad it helped. And using .scan instead makes sense. Nice job working that out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.