How can I get the username without the # symbol?
That's everything between # and any non-word character.
message = <<-MESSAGE
From #victor with love,
To #andrea,
and CC goes to #ghost
MESSAGE
Using a Ruby regular expression, I tried
username_pattern = /#\w+/
I will like to get the following output
message.scan(username_pattern)
#=> ["victor", "andrea", "ghost"]
Use look behind
(?<=#)\w+
this will leave # symbol regex
I would go with:
message.scan(/(?<=#)\w+/)
#=> ["victor","andrea","ghost"]
You might want to read about look-behind regexp.
You could match the # and then capture one or more times a word character in a capturing group
#(\w+)
username_pattern = /#(\w+)/
Regex demo
Try this
irb(main):010:0> message.scan(/#(\w+)/m).flatten
=> ["victor", "andrea", "ghost"]
Related
I am new to ruby and I want to do the following action to remove last "_val3" in ruby:
$ val="val1_val2_val3"
$ echo ${val%_*}
val1_val2
I used to use echo ${val%_*} to get "val1_val2", but i do not how do this in ruby.
Also, how to get "val1"?
Is there a good way to do them?
Not a ruby expert but I'll get the ball rolling with a regular expression:
a.sub /_[^_]*$/, ''
Match an underscore followed by any number of non-underscores at the end of the string. Replace with nothing.
You can use a single gsub to get your expected o/p,
a = "a-b_c_d"
# => "a-b_c_d"
a.gsub /_[a-z]*$/, ''
# => "a-b_c"
Or, you can use ruby split and join,
a.split("_")[0..-2].join("_")
# => "a-b_c"
String#rpartition would probably work:
'a-b_c_d'.rpartition('_') #=> ["a-b_c", "_", "d"]
rpartition looks for the last '_' and returns an array containing the part before it, the separator itself and the part after it.
I am trying to use gsub or sub on a regex passed through terminal to ARGV[].
Query in terminal: $ruby script.rb input.json "\[\{\"src\"\:\"
Input file first 2 lines:
[{
"src":"http://something.com",
"label":"FOO.jpg","name":"FOO",
"srcName":"FOO.jpg"
}]
[{
"src":"http://something123.com",
"label":"FOO123.jpg",
"name":"FOO123",
"srcName":"FOO123.jpg"
}]
script.rb:
dir = File.dirname(ARGV[0])
output = File.new(dir + "/output_" + Time.now.strftime("%H_%M_%S") + ".json", "w")
open(ARGV[0]).each do |x|
x = x.sub(ARGV[1]),'')
output.puts(x) if !x.nil?
end
output.close
This is very basic stuff really, but I am not quite sure on how to do this. I tried:
Regexp.escape with this pattern: [{"src":".
Escaping the characters and not escaping.
Wrapping the pattern between quotes and not wrapping.
Meditate on this:
I wrote a little script containing:
puts ARGV[0].class
puts ARGV[1].class
and saved it to disk, then ran it using:
ruby ~/Desktop/tests/test.rb foo /abc/
which returned:
String
String
The documentation says:
The pattern is typically a Regexp; if given as a String, any regular expression metacharacters it contains will be interpreted literally, e.g. '\d' will match a backlash followed by ādā, instead of a digit.
That means that the regular expression, though it appears to be a regex, it isn't, it's a string because ARGV only can return strings because the command-line can only contain strings.
When we pass a string into sub, Ruby recognizes it's not a regular expression, so it treats it as a literal string. Here's the difference in action:
'foo'.sub('/o/', '') # => "foo"
'foo'.sub(/o/, '') # => "fo"
The first can't find "/o/" in "foo" so nothing changes. It can find /o/ though and returns the result after replacing the two "o".
Another way of looking at it is:
'foo'.match('/o/') # => nil
'foo'.match(/o/) # => #<MatchData "o">
where match finds nothing for the string but can find a hit for /o/.
And all that leads to what's happening in your code. Because sub is being passed a string, it's trying to do a literal match for the regex, and won't be able to find it. You need to change the code to:
sub(Regexp.new(ARGV[1]), '')
but that's not all that has to change. Regexp.new(...) will convert what's passed in into a regular expression, but if you're passing in '/o/' the resulting regular expression will be:
Regexp.new('/o/') # => /\/o\//
which is probably not what you want:
'foo'.match(/\/o\//) # => nil
Instead you want:
Regexp.new('o') # => /o/
'foo'.match(/o/) # => #<MatchData "o">
So, besides changing your code, you'll need to make sure that what you pass in is a valid expression, minus any leading and trailing /.
Based on this answer in the thread Convert a string to regular expression ruby, you should use
x = x.sub(/#{ARGV[1]}/,'')
I tested it with this file (test.rb):
puts "You should not see any number [0123456789].".gsub(/#{ARGV[0]}/,'')
I called the file like so:
ruby test.rb "\d+"
# => You should not see any number [].
I need to determine if a given string has the sequence dash-alpha-alpha-dash.
Example strings:
114888-ZV-209897
409-II-224858
86296-MO-184080
2459-ND-217906
What would be the the regex to determine that?
I'm using Ruby 1.9.3, FWIW.
if subject =~ /-[A-Z]{2}-/
# Successful match
else
# Match attempt failed
end
That [A-Z] thingy is a character class.
It's a simple pattern:
/-[A-Z]{2}-/
will do it.
Your regex is available at: http://rubular.com/r/6hn8BLc7rF
For instance:
"114888-ZV-209897"[/-[A-Z]{2}-/]
=> "-ZV-"
So use:
if "114888-ZV-209897"[/-[A-Z]{2}-/] ...
I am trying to escape certain characters in a string. In particular, I want to turn
abc/def.ghi into abc\/def\.ghi
I tried to use the following syntax:
1.9.3p125 :076 > "abc/def.ghi".gsub(/([\/.])/, '\\\1')
=> "abc\\1def\\1ghi"
Hmm. This behaves as if capture replacements didn't work. Yet, when I tried this:
1.9.3p125 :075 > "abc/def.ghi".gsub(/([\/.])/, '\1')
=> "abc/def.ghi"
... I got the replacement to work, but, of course, my prefixes weren't part of it.
What is the correct syntax to do something like this?
This should be easier
gsub(/(?=[.\/])/, "\\")
If you are trying to prepare a string to be used as a regex pattern, use the right tool:
Regexp.escape('abc/def.ghi')
=> "abc/def\\.ghi"
You can then use the resulting string to create a regex:
/#{ Regexp.escape('abc/def.ghi') }/
=> /abc\/def\.ghi/
or:
Regexp.new(Regexp.escape('abc/def.ghi'))
=> /abc\/def\.ghi/
From the docs:
Escapes any characters that would have special meaning in a regular expression. Returns a new escaped string, or self if no characters are escaped. For any string, Regexp.new(Regexp.escape(str))=~str will be true.
Regexp.escape('\*?{}.') #=> \\\*\?\{\}\.
You can pass a block to gsub:
>> "abc/def.ghi".gsub(/([\/.])/) {|m| "\\#{m}"}
=> "abc\\/def\\.ghi"
Not nearly as elegant as #sawa's answer, but it was the only way I could find to get it to work if you need the replacing string to contain the captured group/backreference (rather than inserting the replacement before the look-ahead).
I've been trying to dry up the following regexp that matches hashtags in a string with no success:
/^#(\w+)|\s#(\w+)/i
This won't work:
/^|\s#(\w+)/i
And no, I don't want to comma the alternation at the beginning:
/(^|\s)#(\w+)/i
I'm doing this in Ruby - though that should not be relevant I suppose.
To give some examples of matching and non-matching strings:
'#hashtag it is' # should match => [["hashtag"]]
'this is a #hashtag' # should match => [["hashtag"]]
'this is not a#hashtag' # should not match => []
Any suggestions? Am I nitpicking?
You can use.
/\B#(\w+)/i
"this is a #hash tag" # matches
"#hash tag" # matches
"this is not#hash tag" # doesn't match
/(?:^|\s)#(\w+)/i
Adding the ?: prefix to the first group will cause it to not be a matching group, thus only the second group will actually be a matchgroup. Thus, each match of the string will have a single capturing group, the contents of which will be the hashtag.
This uses look-behind and I don't know if look behinds are supported in Ruby (I heard that they are not supported in JavaScript)
/(^#(\w+))|((?<= )#(\w+))/