sherlock
sherlock

Reputation: 2807

Is it a bug of Ruby parser?

I have slimmed down an issue I am facing to an MWE. Can anybody confirm if it is a bug or I am missing something rudimentary?

Platform:

Step 1: Create a Ruby script as follows named demo.rb

puts "[Line 1]"
puts "* [Line 2] *"

Step 2: Create a driver script as follows named driver

#!/bin/bash

ret=`ruby ./demo.rb `
echo $ret

Step 3: Move both the files above inside an empty folder.

Step 4: Run driver from bash. As you can see, it's listing the contents of the parent directory with each puts call.

$ ./driver
[Line 1] demo.rb driver [Line 2] demo.rb driver

Step 5: If demo.rb is executed directly from bash, it produces:

$ ruby demo.rb 
[Line 1]
* [Line 2] *

Now, delete the asterisks(*) from both the ends of the puts string in the second line of demo.rb:

puts "[Line 1]"
puts " [Line 2] "

If I repeat step 4,

$ ./driver 
[Line 1] [Line 2]

If I repeat step 5,

$ ruby demo.rb 
[Line 1]
 [Line 2] 

I can't understand the following:

  1. Why does the output contain directory listing in the first attempt?
  2. Why does removal of asterisks suppress the directory listing in the second attempt?
  3. Why does the outputs differ in the second attempt if I repeat step 4 and step 5 respectively?

Upvotes: 3

Views: 72

Answers (2)

Amadan
Amadan

Reputation: 198314

1 & 2: Nothing to do with Ruby, everything to do with Bash. * is a glob, which expands to the list of the filenames when present in a bash command. Try this:

$ echo *
$ a="*"; echo $a
$ a="DIR: * ; DIR AGAIN: *"; echo $a

3: Because echo prints its arguments separated by a space; and newlines are treated as spaces. Look at this:

$ a=`cat /etc/services`
$ echo $a
$ echo "$a"

The echo $a will smush all the lines into one. If you use the double quotes, you can protect the contents of $a to be treated as one argument, and the newlines are preserved. (Same logic would apply for echo "$ret")

Upvotes: 7

Tom Fenech
Tom Fenech

Reputation: 74615

Looks like standard glob expansion behaviour to me.

When you do echo $ret in your shell script, the * inside the string is expanded to the contents of the directory.

If you had put quotes around it echo "$ret", then you would only see the literal * in the output. You would also see that the whitespace inside the variable was preserved (answering the third point in your question).

This is one of the reasons why you should always quote your variables!

Upvotes: 2

Related Questions