简体   繁体   中英

Replace all words which don't match a RegExp pattern in Ruby

I have a string in ruby, let's say
"hello, I am a string, I am surrounded by quotes"
and I want to replace all words ( separated by a space ) which don't match a RegExp pattern, lets say /.+?s/ with "foo" . so the result would be
"foo foo foo foo string, foo foo surrounded foo quotes"

since words have a separator I could do

str = "hello, I am a string, I am surrounded by quotes"
str = str.split
str.each{
  |e|
  x = e.match(/(.+)?s/)
  if x.to_s.empty? then e.replace "foo" end
}
str = str.join(" ")
puts str # -> foo foo foo foo string, foo foo surrounded foo quotes

but is there better way of doing this? As that is quite a lot of code for a relatively simple operation.

Replace Any Word That Doesn't Start or End with s

Assuming that your real rule is to exclude words that start or end with the character s , you can split your words and then map String#gsub onto each element. For example, using Ruby 2.7.2+ (I'm actually using 3.0.0-preview1):

str = "hello, i am a string, i am surrounded by quotes"
str.split.map { _1.gsub(/\b[^s]+\b/) { "foo" } }.join ?\s
#=> "foo, foo foo foo string, foo foo surrounded foo quotes"

This will work on earlier Ruby versions, too. Just replace the positional block parameter (eg _1 ) with a named variable like word , and (if you like) replace the shorthand ?\s with "\s" . For example, using Ruby 2.5.8:

str = 'hello, i am a string, i am surrounded by quotes'
str.split.map do |word|
  word.gsub(/\b[^s]+\b/) { 'foo' }
end.join "\s"
#=> "foo, foo foo foo string, foo foo surrounded foo quotes"

The results should be the same either way.

I have a string in ruby, let's say
"hello, I am a string, I am surrounded by quotes"
and I want to replace all words ( separated by a space ) which don't match a RegExp pattern, lets say /.+?s/ with "foo" . so the result would be
"foo foo foo foo string, foo foo surrounded foo quotes"

since words have a separator I could do

str = "hello, I am a string, I am surrounded by quotes"
str = str.split
str.each{
  |e|
  x = e.match(/(.+)?s/)
  if x.to_s.empty? then e.replace "foo" end
}
str = str.join(" ")
puts str # -> foo foo foo foo string, foo foo surrounded foo quotes

but is there better way of doing this? As that is quite a lot of code for a relatively simple operation.

From your example it appears that you want to replace all words with 'foo' except words that contain 's' ; namely, 'string' , 'surrounded' and 'quotes' . For that you can simplify /(.+)?s/ to /s/ (eg, 'beeswax'.match?(/s/) #=> true ).

It's best to use String#gsub on the entire string as it preserves extra spaces between words. If one instead splits the string on spaces, substitutes for each word in the resulting array, and then join s those elements to form a new string the extra spaces will be removed. For example, if one is old-school and inserts two spaces between sentences, we might have the following.

str = "Hello, I use a string of words, surrounded by quotes.  So there."
                                                             

and want to preserve the two spaces following the period in the resulting string. Moreover, splitting on spaces and then joining the modified words creates an unnecessary array.

Suppose we wish to replace words that do not contain match 's' or 'S' with 'foo' . Words that contain 's' or 'S' match the regular expression

r = /s/i

We may then write:

str.gsub(/\w+/) { |s| s.match?(r) ? s : 'foo' }
  #=> "foo, foo use foo string foo words, surrounded foo quotes.  So foo."

gsub 's argument is a regular expression that matches words.

Consider a second example. Suppose we with to replace all words that neither begin nor end with 's' or 'S' with 'foo' ; that is, words that do not match the regular expression

r = /\As|s\z/i

We can do that in the same way:

str.gsub(/\w+/) { |s| s.match?(r) ? s : 'foo' }
  #=> "foo, foo foo foo string foo words, surrounded foo quotes.  So foo."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM