tags:

views:

129

answers:

2

Why does this line output "z" instead of "?"

$ ruby -e 'puts %x[ echo #{"?"} ]'

Suppose the expression inside the #{...} is a variable that may have the value of "?". How should I modify this script so that the question mark is outputted instead of "z"?

(Please forgive the title of this question -- I don't yet understand what is going on here well enough to provide a more descriptive title.)

+1  A: 

It doesn't?

irb(main):001:0> puts %x[echo #{"?"}]
?
=> nil

Using #{} will give you the value of any variables inside - I'm not sure why you're using it instead of

puts %x[echo "?"]

or just

puts '?'
palmsey
+6  A: 

It's not ruby, it's your shell.

Many shells expand the ? character to match a single character in command line arguments. It's useful, if you have a bunch of files name tempA,temp1,tempB,...,temp9 that you want to delete, but you don't want to delete 'temple'

% rm temp?

So I'm guessing you have a file or directory in your working directory named 'z', and the ? matches that, so it gets replaced by the shell.

Normally, when inside single quotes (like your ruby script) it wouldn't get expanded, but since you're passing the question mark to a shell command, it gets expanded there.

% ruby -e 'puts %x[ echo ? ]'
z
%

Should show you the same behaviour.

Also, if you touch a couple other single character filenames like a b c d, those should show up too:

% touch a b c
% ruby -e 'puts %x[ echo ? ]'
a b c z
%

If you want to avoid this when calling exterior shell commands from within ruby, you'll have to escape any strings you pass out. For most purposes String#inspect should give a good enough escaping.

rampion