Reputation: 9929
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 "
?
Upvotes: 3
Views: 892
Reputation: 19248
If you care about correct escaping of '
via backslash, and consequently of \
as well, the solutions of both answers will fail. See raimo's comment to sawa's answer. user513951's solution fails in the same way:
irb(main):040> x = "b'c"; puts "'#{x}'"
'b'c'
Instead, you can use the following function, that properly escapes '
and \
:
def inspect_str_single_quote(s)
"'" + s.gsub(/\\/, "\\\\").gsub(/'/, "\\\\'") + "'"
end
If you want to be able to serialize not just plain strings, but arbitrary data structures, potentially containing strings, you may want to roll your own version of inspect
. Here's a sketch, outlining how it could be done, with TODOs left for the reader:
def inspect_single_quote(value)
case value
when String
inspect_str_single_quote( value
when Array
"[" + value.map { |item| inspect_str_single_quote(item) }.join(", ") + "]"
when Hash
TODO follow "Array" example
when Set
TODO follow "Array" example
when Range # to handle e.g. string ranges
TODO follow "Array" example
when Struct
TODO follow "Array" example
when OpenStruct
TODO follow "Array" example
when Enumerable
TODO follow "Array" example
else # fall back to the default inspect, and hope for the best
value.inspect
end
end
Upvotes: 0
Reputation: 13690
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'
Upvotes: 2
Reputation: 168209
s = 'a"c'.inspect
s[0] = s[-1] = "'"
puts s.gsub("\\\"", "\"") #=> 'a"c'
Upvotes: 2