Differencebetween Gsub and Sub Methods for Ruby Strings

What is the difference between gsub and sub methods for Ruby Strings

The g stands for global, as in replace globally (all):

In irb:

>> "hello".sub('l', '*')
=> "he*lo"
>> "hello".gsub('l', '*')
=> "he**o"

What exactly is gsub in Ruby?

In Ruby, Gsub is a method that can be called on strings. It replaces all instances of a substring with another one inside the string.

Sub is short for "substitute," and G stands for "global." Think of Gsub like a "replace all" function.

The general pattern is str.gsub("target string", "replacement string").

In your example, nothing changes because there are no spaces in the string "hello" that can be replaced with a "-" character.

"hello".gsub(" ","-")

The following example replaces the "!" in "hello!" with ", world", printing "hello, world!"

puts "hello!".gsub("!",", world!")

The following example replaces every instance of "!" in "!!!" with "123", printing "123123123"

puts "!!!".gsub("!", "123")

In Ruby, how do sub, gsub (and other text methods) in shell one-liners work without referring to an object?

It turns out that this is an instance method defined on Kernel, which magically gets turned on only when you use the -p or -n flag.

ruby -pe 'puts method(:gsub);'

#<Method: Object(Kernel)#gsub>

See the documentation here.

Other magical methods I found are chop, print, and sub.

The magical methods are all sent to $_ implicitly.

Ruby: sub/gsub at a particular line OR before/after a pattern

Here is the answer.

File.open("file.txt", "r").each_line do |line|
if line =~ /minor mistakes/
puts "Hello, how are you ?"
end
puts "#{line}"
end

Here is ruby one-liner.

ruby -pe 'puts "Hello, how are you ?" if $_ =~ /minor mistakes/' < file.txt

using gsub in ruby strings correctly

Your second attempt was very close. The problem is that you left a space after the closing bracket, meaning it was only looking for one of those symbols followed by a space.

Try this:

channelName = rhash["Channel"].gsub(/[':;]/, " ")

ruby .gsub replace/substitute a specific range of indexes

That's one approach to solving your issue. I'd like to suggest an alternative for consideration. You are seeking to capitalize any instance of an article in your title except if that instance is at the beginning of the title. You can handle the second part of that by using .each_with_index. For the first part, you can create an array of the target words and then search for the word in the target array like so:

def fix
articles = ["a", "and", "the", "of"]

word_array = title.downcase.split(" ")
new_array = []

word_array.each_with_index do |word, index|
if index == 0 || !articles.include?(word)
new_array << word.capitalize
else
new_array << word
end
end
new_array.join(" ")
end

So .downcase will "normalize" your title so all the words are lowercase. .split(" ") will turn your string into an array of words (cutting at every space). You'll then visit every element of that array using .each_with_index. This method gives you access to the element and the index. You can then check whether you are at index 0 OR the negation of whether this particular element is an article. .includes? checks if the argument passed to it is an element of the array it is being called on. It returns true or false based on if it is or not. With ! before it, we are negating the result (turning true into false and false into true) because we only care if the word is NOT in the array. At the end, we are calling `.join(" ") to deliver a string separating every word with a space as expected.

Performance implications of string#gsub chains?

str.tr('-_', ' ') 

is worth considering (doc)

How does 'String#gsub { }' (with a block) work?

The documentation of method String#gsub explains how it works, depending of what parameters it gets:

gsub(pattern, replacement)new_str
gsub(pattern, hash)new_str
gsub(pattern) {|match| block }new_str
gsub(pattern)enumerator

Returns a copy of str with all occurrences of pattern substituted for the second argument. 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 backslash followed by d, instead of a digit.

If replacement is a String it will be substituted for the matched text. It may contain back-references to the pattern’s capture groups of the form \\d, where d is a group number, or \\k<n>, where n is a group name. If it is a double-quoted string, both back-references must be preceded by an additional backslash. However, within replacement the special match variables, such as $&, will not refer to the current match.

If the second argument is a Hash, and the matched text is one of its keys, the corresponding value is the replacement string.

In the block form, the current match string is passed in as a parameter, and variables such as $1, $2, $`, $&, and $' will be set appropriately. The value returned by the block will be substituted for the match on each call.

The result inherits any tainting in the original string or any supplied replacement string.

When neither a block nor a second argument is supplied, an Enumerator is returned.

The answer to your question looks straightforward now.
When only one argument is passed (the pattern), "the value returned by the block will be substituted for the match on each call".

Two arguments and a block is a case not covered by the documentation because it is not a valid combination. It seems that when two arguments are passed, String#gsub doesn't expect a block and ignores it.

Update

The purpose of String#gsub is to do a "global search", i.e. find all occurrences of some string or pattern and replace them.

The first argument, pattern, is the string or pattern to search for. There is nothing special about it. It can be a string or a regular expression. String#gsub searches it and finds zero or more matches (occurrences).

With only one argument and no block, String#gsub returns an iterator because it can find the pattern but it doesn't have a replacement string to use.

There are three ways to provide it the replacements for the matches (the first three cases described in the documentation quoted above):

  1. a String is used to replace all the matches; it is usually used to remove parts from a string (by providing the empty string as replacement) or mask fragments of it (credit card numbers, passwords, email addresses etc);
  2. a Hash is used to provide different replacements for each match; it is useful when the matches are known in advance;
  3. a block is provided when the replacements depend on the matched substrings but the matches are not known in advance; for example, a block can convert each matching substring to uppercase and return it to let String#gsub use it as replacement.


Related Topics



Leave a reply



Submit