Way to partially match a Ruby string using Regexp - ruby

I'm working on 2 cases:
assume I have those var:
a = "hello"
b = "hello-SP"
c = "not_hello"
Any partial matches
I want to accept any string that has the variable a inside, so b and c would match.
Patterned match
I want to match a string that has a inside, followed by '-', so b would match, c does not.
I am having problem, because I always used the syntax /expression/ to define Regexp, so how dynamically define an RegExp on Ruby?

You can use the same syntax to use variables in a regex, so:
reg1 = /#{a}/
would match on anything that contains the value of the a variable (at the time the expression is created!) and
reg2 = /#{a}-/
would do the same, plus a hyphen, so hello- in your example.
Edit: As Wayne Conrad points out, if a contains "any characters that would have special meaning in a regular expression," you need to escape them. Example:
a = ".com"
b = Regexp.new(Regexp.escape(a))
"blah.com" =~ b

Late to comment but I wasn't able to find what I was looking for.The above mentioned answers didn't help me.Hope it help someone new to ruby who just wants a quick fix.
Ruby Code:
st = "BJ's Restaurant & Brewery"
#take the string you want to match into a variable
m = (/BJ\'s/i).match(string) #(/"your regular expression"/.match(string))
# m has the match #<MatchData "BJ's">
m.to_s
# this will display the match
=> "BJ's"

Related

Find strings that match two regular expressions

The two regexes:
regex_1 = /^A+\S{2}$/
regex_2 = /^AB+\d{1}$/
match the following ten strings:
AB0
AB1
AB2
AB3
AB4
AB5
AB6
AB7
AB8
AB9
Is there a way to find strings that match two regular expressions that are given?
I have a regex, and it will be sliced to many sub-regexes as follows.
Example 1:
original_regex = /^A+\S{2}$/
sub_regex1 = /^AB+\S{1}$/
sub_regex2 = /^AC+\S{1}$/
Example 2:
original_regex = /^598+\S{5}$/
sub_regex1 = /^598A+\S{4}$/
sub_regex2 = /^598AB+\S{3}$/
I want to know whether there are any strings that match all sub-regexes.
I am thinking to convert the regex to a string and compare the minimal-length prefix and the minimal-length suffix like this:
regex_1 = "/^A+\S{2}$/"
regex_2 = "/^AB+\d{1}$/"
regex_3 = "/^AC+\d{1}$/"
minimal_prefix = "/^A"
Any regex string that contains minimal_prefix has a string that matches all sub-regexes. I am figuring out whether this is correct or not.
Is there a quick way in general? No. What are "all the strings" that match these pairs of regular expressions:
/.*/ and /\d*/? (There are infinitely many!)
/\A\d{10}\z/ and /\A[0-8]{10}\z/? (There are 3,486,784,401!)
/\w+\d{2,4}#?([[:punct:]]|\w){2}/ and /(^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)/ (I haven't even tried to work this out; my point is: you could provide arbitrarily complicated input!!)
...But for simple scenarios, such as what you've actually asked, it would be feasible to use this ruby gem:
/^A+\S{2}$/.examples(max_group_results: 999) & /^AB+\d{1}$/.examples(max_group_results: 999)
=> ["AB0", "AB1", "AB2", "AB3", "AB4", "AB5", "AB6", "AB7", "AB8", "AB9"]

best way to find substring in ruby using regular expression

I have a string https://stackverflow.com. I want a new string that contains the domain from the given string using regular expressions.
Example:
x = "https://stackverflow.com"
newstring = "stackoverflow.com"
Example 2:
x = "https://www.stackverflow.com"
newstring = "www.stackoverflow.com"
"https://stackverflow.com"[/(?<=:\/\/).*/]
#⇒ "stackverflow.com"
(?<=..) is a positive lookbehind.
If string = "http://stackoverflow.com",
a really easy way is string.split("http://")[1]. But this isn't regex.
A regex solution would be as follows:
string.scan(/^http:\/\/(.+)$/).flatten.first
To explain:
String#scan returns the first match of the regex.
The regex:
^ matches beginning of line
http: matches those characters
\/\/ matches //
(.+) sets a "match group" containing any number of any characters. This is the value returned by the scan.
$ matches end of line
.flatten.first extracts the results from String#scan, which in this case returns a nested array.
You might want to try this:
#!/usr/bin/env ruby
str = "https://stackoverflow.com"
if mtch = str.match(/(?::\/\/)(/S)/)
f1 = mtch.captures
end
There are two capturing groups in the match method: the first one is a non-capturing group referring to your search pattern and the second one referring to everything else afterwards. After that, the captures method will assign the desired result to f1.
I hope this solves your problem.

regex replace [ with \[

I want to write a regex in Ruby that will add a backslash prior to any open square brackets.
str = "my.name[0].hello.line[2]"
out = str.gsub(/\[/,"\\[")
# desired out = "my.name\[0].hello.line\[2]"
I've tried multiple combinations of backslashes in the substitution string and can't get it to leave a single backslash.
You don't need a regular expression here.
str = "my.name[0].hello.line[2]"
puts str.gsub('[', '\[')
# my.name\[0].hello.line\[2]
I tried your code and it worked correct:
str = "my.name[0].hello.line[2]"
out = str.gsub(/\[/,"\\[")
puts out #my.name\[0].hello.line\[2]
If you replace putswith p you get the inspect-version of the string:
p out #"my.name\\[0].hello.line\\[2]"
Please see the " and the masked \. Maybe you saw this result.
As Daniel already answered: You can also define the string with ' and don't need to mask the values.

Ruby regular expression

Apparently I still don't understand exactly how it works ...
Here is my problem: I'm trying to match numbers in strings such as:
910 -6.258000 6.290
That string should gives me an array like this:
[910, -6.2580000, 6.290]
while the string
blabla9999 some more text 1.1
should not be matched.
The regex I'm trying to use is
/([-]?\d+[.]?\d+)/
but it doesn't do exactly that. Could someone help me ?
It would be great if the answer could clarify the use of the parenthesis in the matching.
Here's a pattern that works:
/^[^\d]+?\d+[^\d]+?\d+[\.]?\d+$/
Note that [^\d]+ means at least one non digit character.
On second thought, here's a more generic solution that doesn't need to deal with regular expressions:
str.gsub(/[^\d.-]+/, " ").split.collect{|d| d.to_f}
Example:
str = "blabla9999 some more text -1.1"
Parsed:
[9999.0, -1.1]
The parenthesis have different meanings.
[] defines a character class, that means one character is matched that is part of this class
() is defining a capturing group, the string that is matched by this part in brackets is put into a variable.
You did not define any anchors so your pattern will match your second string
blabla9999 some more text 1.1
^^^^ here ^^^ and here
Maybe this is more what you wanted
^(\s*-?\d+(?:\.\d+)?\s*)+$
See it here on Regexr
^ anchors the pattern to the start of the string and $ to the end.
it allows Whitespace \s before and after the number and an optional fraction part (?:\.\d+)? This kind of pattern will be matched at least once.
maybe /(-?\d+(.\d+)?)+/
irb(main):010:0> "910 -6.258000 6.290".scan(/(\-?\d+(\.\d+)?)+/).map{|x| x[0]}
=> ["910", "-6.258000", "6.290"]
str = " 910 -6.258000 6.290"
str.scan(/-?\d+\.?\d+/).map(&:to_f)
# => [910.0, -6.258, 6.29]
If you don't want integers to be converted to floats, try this:
str = " 910 -6.258000 6.290"
str.scan(/-?\d+\.?\d+/).map do |ns|
ns[/\./] ? ns.to_f : ns.to_i
end
# => [910, -6.258, 6.29]

Regex to leave desired string remaining and others removed

In Ruby, what regex will strip out all but a desired string if present in the containing string? I know about /[^abc]/ for characters, but what about strings?
Say I have the string "group=4&type_ids[]=2&type_ids[]=7&saved=1" and want to retain the pattern group=\d, if it is present in the string using only a regex?
Currently, I am splitting on & and then doing a select with matching condition =~ /group=\d/ on the resulting enumerable collection. It works fine, but I'd like to know the regex to do this more directly.
Simply:
part = str[/group=\d+/]
If you want only the numbers, then:
group_str = str[/group=(\d+)/,1]
If you want only the numbers as an integer, then:
group_num = str[/group=(\d+)/,1].to_i
Warning: String#[] will return nil if no match occurs, and blindly calling nil.to_i always returns 0.
You can try:
$str =~ s/.*(group=\d+).*/\1/;
Typically I wouldn't really worry too much about a complex regex. Simply break the string down into smaller parts and it becomes easier:
asdf = "group=4&type_ids[]=2&type_ids[]=7&saved=1"
asdf.split('&').select{ |q| q['group'] } # => ["group=4"]
Otherwise, you can use regex a bunch of different ways. Here's two ways I tend to use:
asdf.scan(/group=\d+/) # => ["group=4"]
asdf[/(group=\d+)/, 1] # => "group=4"
Try:
str.match(/group=\d+/)[0]

Resources