Capturing STDOUT from a system call (POSIX) into an array

V

Venks

What's the best way to capture STDOUT into an Array? I looked at
popen3, open4, systemu but couldn't figure out how to do this.

In short, I want to execute a system call like "ls -l" and capture it
into an array. Of course, "ls -l" may not have proper delimiter but
assume that the delimiter is TAB or COMMA.

Thanks,
 
P

Phrogz

What's the best way to capture STDOUT into an Array? I looked at
popen3, open4, systemu but couldn't figure out how to do this.

In short, I want to execute a system call like "ls -l" and capture it
into an array. Of course, "ls -l" may not have proper delimiter but
assume that the delimiter is TAB or COMMA.

lines = `ls -l`.split( /\n/ )
 
K

Ken Bloom

What's the best way to capture STDOUT into an Array? I looked at popen3,
open4, systemu but couldn't figure out how to do this.

In short, I want to execute a system call like "ls -l" and capture it
into an array. Of course, "ls -l" may not have proper delimiter but
assume that the delimiter is TAB or COMMA.

Thanks,

You can use the IO objects returned by popen3 in any way that you'd use a
normal file. To get an array of lines, one string per line, use
#readlines. To parse it as a CSV, for example, the csv library in ruby
should work with CSV.parse

--Ken
 
V

Venks

Thanks for your quick reply. I realize that you don't even need to use
split. What I am missing is how to create a 2 dimensional array with
each line contents in an array assuming that they are separated by a
COMMA.

Let me be more specific. Assume that we have a file under
/tmp/test.txt with the following contents.

aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4

I want to create a 2 dimensional array with each line being an array.

lines = `cat /tmp/test.txt` will create a single dimensional array by default.

Thanks,
 
V

Venks

Actually, the output is not in a file. The output is generated by a
system call. I somehow think there is something simple in Ruby that I
can use to covert the STDOUT to a 2 dimensional array without actually
using any IO objects.
 
A

Alex Gutteridge

Thanks for your quick reply. I realize that you don't even need to use
split. What I am missing is how to create a 2 dimensional array with
each line contents in an array assuming that they are separated by a
COMMA.

Let me be more specific. Assume that we have a file under
/tmp/test.txt with the following contents.

aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4

I want to create a 2 dimensional array with each line being an array.

lines = `cat /tmp/test.txt` will create a single dimensional array
by default.

I'm not so sure about that last comment. As far as I know backticks
always return a String.

The easiest way to do what you want is just to split the String from
backticks by line and then each line by whatever delimiter you chose.
You can do this with map for instance:

[alexg@powerbook]/Users/alexg/Desktop(47): cat test.txt
aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4
[alexg@powerbook]/Users/alexg/Desktop(48): cat capture.rb
p `cat #{ARGV[0]}`.split(/\n/).map{|line| line.split(/, /)}
[alexg@powerbook]/Users/alexg/Desktop(49): ruby capture.rb test.txt
[["aaa", "10", "test1"], ["bbb", "20", "test2"], ["ccc", "30",
"test3"], ["ddd", "40", "test4"]]

Alex Gutteridge

Bioinformatics Center
Kyoto University
 
V

Venks

Thanks for your reply. It works now. I was looking for the method
"map" over "split".

Thanks for your quick reply. I realize that you don't even need to use
split. What I am missing is how to create a 2 dimensional array with
each line contents in an array assuming that they are separated by a
COMMA.

Let me be more specific. Assume that we have a file under
/tmp/test.txt with the following contents.

aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4

I want to create a 2 dimensional array with each line being an array.

lines = `cat /tmp/test.txt` will create a single dimensional array
by default.

I'm not so sure about that last comment. As far as I know backticks
always return a String.

The easiest way to do what you want is just to split the String from
backticks by line and then each line by whatever delimiter you chose.
You can do this with map for instance:

[alexg@powerbook]/Users/alexg/Desktop(47): cat test.txt
aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4
[alexg@powerbook]/Users/alexg/Desktop(48): cat capture.rb
p `cat #{ARGV[0]}`.split(/\n/).map{|line| line.split(/, /)}
[alexg@powerbook]/Users/alexg/Desktop(49): ruby capture.rb test.txt
[["aaa", "10", "test1"], ["bbb", "20", "test2"], ["ccc", "30",
"test3"], ["ddd", "40", "test4"]]

Alex Gutteridge

Bioinformatics Center
Kyoto University
 
V

Venks

Also, I tried collect! method earlier, but didn't know how to apply
split within collect!. After seeing your example I understood the
proper syntax. I also understand that map and collect! are the same.

Thanks for your reply. It works now. I was looking for the method
"map" over "split".


Thanks for your quick reply. I realize that you don't even need to use
split. What I am missing is how to create a 2 dimensional array with
each line contents in an array assuming that they are separated by a
COMMA.

Let me be more specific. Assume that we have a file under
/tmp/test.txt with the following contents.

aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4

I want to create a 2 dimensional array with each line being an array.

lines = `cat /tmp/test.txt` will create a single dimensional array
by default.

I'm not so sure about that last comment. As far as I know backticks
always return a String.

The easiest way to do what you want is just to split the String from
backticks by line and then each line by whatever delimiter you chose.
You can do this with map for instance:

[alexg@powerbook]/Users/alexg/Desktop(47): cat test.txt
aaa, 10, test1
bbb, 20, test2
ccc, 30, test3
ddd, 40, test4
[alexg@powerbook]/Users/alexg/Desktop(48): cat capture.rb
p `cat #{ARGV[0]}`.split(/\n/).map{|line| line.split(/, /)}
[alexg@powerbook]/Users/alexg/Desktop(49): ruby capture.rb test.txt
[["aaa", "10", "test1"], ["bbb", "20", "test2"], ["ccc", "30",
"test3"], ["ddd", "40", "test4"]]

Alex Gutteridge

Bioinformatics Center
Kyoto University
 
S

Sebastian Hungerecker

Venks said:
I also understand that map and collect! are the same.

map and collect are the same. As are map! and collect!.
map/collect and map!/collect! however are NOT the same.
Consider this:

arr = [1,2,3]
p arr.map {|x| x+1} # Prints [2, 3, 4]
p arr # Prints [1, 2, 3]

arr = [1,2,3]
p arr.map! {|x| x+1} # Prints [2, 3, 4]
p a # Prints [2, 3, 4] too.


HTH,
Sebastian
 
V

Venks

Thanks.

Unfortunately I learned the hard way that if I use back ticks to
execute an external command STDERR is not captured. I need to check
the status of the command before proceeding. I am looking into
"systemu" library as I may need to use threads as part of this
development process.
 
M

MonkeeSage

Thanks.

Unfortunately I learned the hard way that if I use back ticks to
execute an external command STDERR is not captured. I need to check
the status of the command before proceeding. I am looking into
"systemu" library as I may need to use threads as part of this
development process.

You can always use shell redirection to redirect stderr to stdout...

s = p `ls nonexistent_dir 2>&1`
p s
# => "ls: cannot access nonexistent_dir: No such file or directory\n"

Regards,
Jordan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top