I'm experimenting with writing a text filter, as a learning
experience.
Right now, I want the program to:
* work as a pure filter if there are no command-line arguments
* use the argument as an input file, send output to STOUT if there is
one argument
* If there are more than one argument, use the last argument as
an output file name and the others as input file names.
My question is not how to get my program to do this. It is doing it
exactly as I wanted, like a mind reader. My question is, how is it so
smart? I expect I'll have problems later on if I don't really
understand what is happening.
I have read that unless somehow told otherwise, a Ruby program uses
the command-line arguments as input file names and reads them one
after the other as though they came from STDIN. If I have used the
last argument as an output file name, why doesn't it run into trouble
when it comes to this argument and tries to use it as in input file?
And how, in general, do I make sure that a Ruby script does not try to
use an argument as an input file name if I want it to mean something
else?
Scratching my head (with delight for a change).
Thank you for any help.
(This is my program so far.
#!/usr/bin/env ruby
# Reverses characters in every line of a file
if STDIN.tty?
puts "No. of args = #{ARGV.size}"
ARGV.each { |a| puts "Arg = #{a}" }
if ARGV.size>1
$stdout=File.new(ARGV[ARGV.size-1], "w")
end
end
while line = gets
line.chomp!
puts line.reverse
end
"Paul Emmons" <pemmons@voicenet.com> schrieb im Newsbeitrag
news:cln9c0tv0r26fgt25hq43htmlh5sk709id@4ax.com...
I'm experimenting with writing a text filter, as a learning
experience.
Right now, I want the program to:
* work as a pure filter if there are no command-line arguments
* use the argument as an input file, send output to STOUT if there is
one argument
* If there are more than one argument, use the last argument as
an output file name and the others as input file names.
My question is not how to get my program to do this. It is doing it
exactly as I wanted, like a mind reader. My question is, how is it so
smart? I expect I'll have problems later on if I don't really
understand what is happening.
I have read that unless somehow told otherwise, a Ruby program uses
the command-line arguments as input file names and reads them one
after the other as though they came from STDIN. If I have used the
last argument as an output file name, why doesn't it run into trouble
when it comes to this argument and tries to use it as in input file?
And how, in general, do I make sure that a Ruby script does not try to
use an argument as an input file name if I want it to mean something
else?
Scratching my head (with delight for a change).
Thank you for any help.
(This is my program so far.
#!/usr/bin/env ruby
# Reverses characters in every line of a file
if STDIN.tty?
puts "No. of args = #{ARGV.size}"
ARGV.each { |a| puts "Arg = #{a}" }
if ARGV.size>1
$stdout=File.new(ARGV[ARGV.size-1], "w")
end
end
#!/usr/bin/ruby
out = nil
case ARGV.size
when 0, 1
out = $stdout
else
out = File.open( ARGV.slice!(-1,1)[0], "w" )
end
begin
while line = gets
line.chomp!
out.puts line.reverse
end
ensure
out.close unless out.equal? $stdout
end
I have read that unless somehow told otherwise, a Ruby program uses
the command-line arguments as input file names and reads them one
after the other as though they came from STDIN. If I have used the
last argument as an output file name, why doesn't it run into trouble
when it comes to this argument and tries to use it as in input file?
If you are only testing with small input files, then the last input file
may well be empty when you try to read from it.
#!/usr/bin/env ruby
# Reverses characters in every line of a file
if STDIN.tty?
puts "No. of args = #{ARGV.size}"
ARGV.each { |a| puts "Arg = #{a}" }
if ARGV.size>1
$stdout=File.new(ARGV[ARGV.size-1], "w")
This truncates the last file to zero bytes.
end
end
while line = gets
line.chomp!
puts line.reverse
This puts a reversed line into a buffer. It does not write anything to
the last file until the buffer is full.
end
So, for small input files, everything goes into a buffer. When you try to
read a line from the last file, there are no lines; the loop ends, the
buffer flushes, and all is well.
For larger input files, the buffer gets flushed earlier, so there are
actual lines to read from the last file. Those lines get read, then
written to the end of the file, where they are read again, and written
again, and read, and written...