Use single quote in string inspection - ruby

I have the following program:
args = ["a", "b"]
cmd_args = args.map{|x| x.inspect}
str = cmd_args.join(' ')
puts str
The output is:
"a" "b"
I expect the output to be like the following (sub-string quoted with ' instead of "):
'a' 'b'
I don't want to do a gsub after string inspect because, in my real system, substring might contain ". For example:
args = ['a"c', "b"]
cmd_args = args.map{|x| x.inspect.gsub('"', '\'')}
str = cmd_args.join(' ')
puts str
will output:
'a\'c' 'b'
The " between a and c is wrongly replaced. My expected output is:
'a"c' 'b'
How can I make string inspect to quote strings with ' instead of "?

s = 'a"c'.inspect
s[0] = s[-1] = "'"
puts s.gsub("\\\"", "\"") #=> 'a"c'

You can't force String#inspect to use a single quote without rewriting or overwriting it.
Instead of x.inspect, you could substitute "'#{x}'", but then you would have to make sure you escape any ' characters that appear in x.
Here it is, working:
args = ["a", "b"]
cmd_args = args.map{|x| "'#{x}'" }
str = cmd_args.join(' ')
puts str
The output is:
'a' 'b'

Related

how I could do a gsub with array elements?

How I could replaces a string like this
I think something like this
inputx.gsub(/variable1/,string1.split(";")[i])
But I dont know How I could do this code
name1;variable1
name;variable1
name3;variable1
by
dog;watch;rock
For obtain this
name1;dog
name;watch
name3;rock
string1 => dog;watch;rock ; this string Im trying to split for replace each string variable1
Please help me
subst = "dog;watch;rock".split ';'
input.gsub(/variable1/) do subst.shift end
#⇒ "name1;dog \n name;watch \n name3;rock"
Given (assuming) this input:
inputx = <<-EOD
name1;variable1
name;variable1
name3;variable1
EOD
#=> "name1;variable1\nname;variable1\nname3;variable1\n"
string1 = 'dog;watch;rock'
#=> "dog;watch;rock"
You can chain gsub and with_index to perform a replacement based on its index:
inputx.gsub('variable1').with_index { |_, i| string1.split(';')[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
You could also perform the split beforehand:
values = string1.split(';')
#=> ["dog", "watch", "rock"]
inputx.gsub('variable1').with_index { |_, i| values[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
I'm not sure there's a way to do it using .gsub(). One simple way to achieve what you want to is the following:
str = "dog;watch;rock"
array = str.split(";")
array.each_with_index do |str, i|
array[i] = "name#{i + 1};#{str}"
end
puts array
Output:
name1;dog
name2;watch
name3;rock
file intro2 => dog;watch;rock
file intro
name1;variable1
name;variable1
name3;variable1
ruby code
ruby -e ' n=0; input3= File.read("intro");string1= File.read("intro2") ;input3x=input3.gsub("variable1") { val =string1.split(";")[n].to_s; n+=1; val } ;print input3x' >gggf

Convert a string based on hash values [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
I am trying to write a method that takes in a string and a hash and "encodes" the string based on hash keys and values.
def encode(str,encoding)
end
str = "12#3"
encoding = {"1" => "one", "2"=> "two", "3"=> "three"}
I am expecting the output to be "one two three" any char in the string that is not a key in the hash is replaced with an empty string.
Right now my code looks like the following:
def encode(str, encoding)
output = ""
str.each_char do |ch|
if encoding.has_key?(ch)
output += encoding[ch]
else
output += ""
end
end
return output
end
Any help is appreciated
You can use use the form of String#gsub that uses a hash for substitutions, and a simple regex:
str = "12#3"
encoding = {"1"=>"one", "2"=>"two", "3"=>"three"}
First create a new hash that adds a space to each value in encoding:
adj_encoding = encoding.each_with_object({}) { |(k,v),h| h[k] = "#{v} " }
#=> {"1"=>"one ", "2"=>"two ", "3"=>"three "}
Now perform the substitutions and strip off the extra space if one of the keys of encoding is the last character of str:
str.gsub(/./, adj_encoding).rstrip
#=> "one two three"
Another example:
"1ab 2xx4cat".gsub(/./, adj_encoding).rstrip
#=> "one two"
Ruby determines whether each character of str (the /./ part) equals a key of adj_encodeing. If it does, she substitutes the key's value for the character; else she substitutes an empty string ('') for the character.
You can build a regular expression that matches your keys via Regexp.union:
re = Regexp.union(encoding.keys)
#=> /1|2|3/
scan the string for occurrences of keys using that regular expression:
keys = str.scan(re)
#=> ["1", "2", "3"]
fetch the corresponding values using values_at:
values = encoding.values_at(*keys)
#=> ["one", "two", "three"]
and join the array with a single space:
values.join(' ')
#=> "one two three"
As a "one-liner":
encoding.values_at(*str.scan(Regexp.union(encoding.keys))).join(' ')
#=> "one two three"
Try:
def encode(str, encoding)
output = ""
str.each_char do |ch|
if encoding.has_key?(ch)
output += encoding[ch] + " "
else
output += ""
end
end
return output.split.join(' ')
end
str = "12#3"
encoding = {"1" => "one", "2"=> "two", "3"=> "three"}
p encode(str, encoding) #=> "one two three"
If you are expecting "one two three" you just need to add an space to your concat line and before return, add .lstrip to remove the first space.
Hint: You don't need the "else" concatenating an empty string. If the "#" don't match the encoding hash, it will be ignored.
Like this:
#str = "12#3"
#encoding = {"1" => "one", "2"=> "two", "3"=> "three"}
def encode(str, encoding)
output = ""
str.each_char do |ch|
if encoding.has_key?(ch)
output += " " + encoding[ch]
end
end
return output.lstrip
end
# Output: "one two three"
I would do:
encoding = {"1" => "one", "2"=> "two", "3"=> "three"}
str = "12#3"
str.chars.map{|x|encoding.fetch(x,nil)}.compact.join(' ')
Or two lines like this:
in_encoding_hash = -> x { encoding.has_key? x }
str.chars.grep(in_encoding_hash){|x|encoding[x]}.join(' ')

How could I split commas excepts it's in double quotes

s1 ='a,b,c,"x,y,z" '
m1 = s1.split(',')
"x,y,z" should not be splitted by comma
The expected result should be ['a','b','c',"x,y,z"], total size is 4
How could I do that in Ruby
Use the csv module:
irb(main):001:0> require 'csv'
=> true
irb(main):002:0> CSV.parse_line('a,b,c,"x,y,z"')
=> ["a", "b", "c", "x,y,z"]
Try this:
s1 ='a,b,c,"x,y,z" '
quotes = s1.match(/".+"/)
s1.split(/,(?![#{quotes}])|,(?=")/)
Could it be? Is it possible? Do I finally have a chance to use Ruby's bordering-on-bizarre flip-flop operator?
Let's try:
str ='a,b,c,"x,y,z",d,e,"1,2,3",f '
u = ''
str.split(?,).each_with_object([]) do |s,a|
t = s.strip
if (t[0]==?") .. (t[-1]==?")
u = '' if t[0]==?"
u << t
if t[-1]==?"
a << u
else
u << ?,
end
else
a << t
end
end
#=> ["a", "b", "c", "\"x,y,z\"", "d", "e", "\"1,2,3\"", "f"]
You can do a one liner def like this that will separate the string by commas, unless the commas are inside simple OR double quotes
def separate params
params.split(/(?!\B\b('|")[^\"']*),(?![^\"']*('|")\B\b)/)
end

Replacing a char in Ruby with another character

I'm trying to replace all spaces in a string with '%20', but it's not producing the result I want.
I'm splitting the string, then going through each character. If the character is " " I want to replace it with '%20', but for some reason it is not being replaced. What am I doing wrong?
def twenty(string)
letters = string.split("")
letters.each do |char|
if char == " "
char = '%20'
end
end
letters.join
end
p twenty("Hello world is so played out")
Use URI.escape(...) for proper URI encoding:
require 'uri'
URI.escape('a b c') # => "a%20b%20c"
Or, if you want to roll your own as a fun learning exercise, here's my solution:
def uri_escape(str, encode=/\W/)
str.gsub(encode) { |c| '%' + c.ord.to_s(16) }
end
uri_escape('a b!c') # => "a%20%20b%21c"
Finally, to answer your specific question, your snippet doesn't behave as expected because the each iterator does not mutate the target; try using map with assignment (or map!) instead:
def twenty(string)
letters = string.split('')
letters.map! { |c| (c == ' ') ? '%20' : c }
letters.join
end
twenty('a b c') # => "a%20b%20c"
If you want to first split the string on spaces, you could do this:
def twenty(string)
string.split(' ').join('%20')
end
p twenty("Hello world is so played out")
#=> "Hello%20world%20is%20so%20played%20out"
Note that this is not the same as
def twenty_with_gsub(string)
string.gsub(' ', '%20')
end
for if
string = 'hi there'
then
twenty(string)
#=> "hi%20there"
twenty_with_gsub(string)
#=> "hi%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20there"

How do you strip substrings in ruby?

I'd like to replace/duplicate a substring, between two delimeters -- e.g.,:
"This is (the string) I want to replace"
I'd like to strip out everything between the characters ( and ), and set that substr to a variable -- is there a built in function to do this?
I would just do:
my_string = "This is (the string) I want to replace"
p my_string.split(/[()]/) #=> ["This is ", "the string", " I want to replace"]
p my_string.split(/[()]/)[1] #=> "the string"
Here are two more ways to do it:
/\((?<inside_parenthesis>.*?)\)/ =~ my_string
p inside_parenthesis #=> "the string"
my_new_var = my_string[/\((.*?)\)/,1]
p my_new_var #=> "the string"
Edit - Examples to explain the last method:
my_string = 'hello there'
capture = /h(e)(ll)o/
p my_string[capture] #=> "hello"
p my_string[capture, 1] #=> "e"
p my_string[capture, 2] #=> "ll"
var = "This is (the string) I want to replace"[/(?<=\()[^)]*(?=\))/]
var # => "the string"
str = "This is (the string) I want to replace"
str.match(/\((.*)\)/)
some_var = $1 # => "the string"
As I understand, you want to remove or replace a substring as well as set a variable equal to that substring (sans the parentheses). There are many ways to do this, some of which are slight variants of the other answers. Here's another way that also allows for the possibility of multiple substrings within parentheses, picking up from #sawa's comments:
def doit(str, repl)
vars = []
str.gsub(/\(.*?\)/) {|m| vars << m[1..-2]; repl}, vars
end
new_str, vars = doit("This is (the string) I want to replace", '')
new_str # => => "This is I want to replace"
vars # => ["the string"]
new_str, vars = doit("This is (the string) I (really) want (to replace)", '')
new_str # => "This is I want"
vars # => ["the string", "really, "to replace"]
new_str, vars = doit("This (short) string is a () keeper", "hot dang")
new_str # => "This hot dang string is a hot dang keeper"
vars # => ["short", ""]
In the regex, the ? in .*? makes .* "lazy". gsub passes each match m to the block; the block strips the parens and adds it to vars, then returns the replacement string. This regex also works:
/\([^\(]*\)/

Resources