ruby stdin

ruby input output



¿Mejores prácticas con STDIN en Ruby? (9)

Quiero lidiar con la entrada de línea de comandos en Ruby:

> cat input.txt | myprog.rb > myprog.rb < input.txt > myprog.rb arg1 arg2 arg3 ...

¿Cuál es la mejor manera de hacerlo? En particular, quiero lidiar con STDIN en blanco, y espero una solución elegante.

#!/usr/bin/env ruby STDIN.read.split("/n").each do |a| puts a end ARGV.each do |b| puts b end


¿Algo así tal vez?

#/usr/bin/env ruby if $stdin.tty? ARGV.each do |file| puts "do something with this file: #{file}" end else $stdin.each_line do |line| puts "do something with this line: #{line}" end end

Ejemplo:

> cat input.txt | ./myprog.rb do something with this line: this do something with this line: is do something with this line: a do something with this line: test > ./myprog.rb < input.txt do something with this line: this do something with this line: is do something with this line: a do something with this line: test > ./myprog.rb arg1 arg2 arg3 do something with this file: arg1 do something with this file: arg2 do something with this file: arg3


A continuación hay algunas cosas que encontré en mi colección de Ruby oscuro.

Por lo tanto, en Ruby, una implementación simple sin complicaciones del comando cat Unix sería:

#!/usr/bin/env ruby puts ARGF.read

ARGF es tu amigo cuando se trata de entrada; es un archivo virtual que obtiene todas las entradas de los archivos nombrados o todos los de STDIN.

ARGF.each_with_index do |line, idx| print ARGF.filename, ":", idx, ";", line end # print all the lines in every file passed via command line that contains login ARGF.each do |line| puts line if line =~ /login/ end

Gracias a Dios, no conseguimos el operador de diamantes en Ruby, pero sí ARGF como reemplazo. Aunque oscuro, en realidad resulta útil. Considere este programa, que antepone encabezados de copyright en el lugar (gracias a otro Perlism, -i ) a cada archivo mencionado en la línea de comandos:

#!/usr/bin/env ruby -i Header = DATA.read ARGF.each_line do |e| puts Header if ARGF.pos - e.length == 0 puts e end __END__ #-- # Copyright (C) 2007 Fancypants, Inc. #++

Crédito a:


Agregaré que para usar ARGF con parámetros, debe borrar ARGV antes de llamar a ARGF.each . Esto se debe a que ARGF tratará cualquier cosa en ARGV como un nombre de archivo y leerá las líneas desde allí primero.

Aquí hay un ejemplo de implementación ''tee'':

File.open(ARGV[0], ''w'') do |file| ARGV.clear ARGF.each do |line| puts line file.write(line) end end


Hago algo como esto:

all_lines = "" ARGV.each do |line| all_lines << line + "/n" end puts all_lines


No estoy muy seguro de lo que necesita, pero usaría algo como esto:

#!/usr/bin/env ruby until ARGV.empty? do puts "From arguments: #{ARGV.shift}" end while a = gets puts "From stdin: #{a}" end

Tenga en cuenta que dado que la matriz ARGV está vacía antes de la primera obtención, Ruby no intentará interpretar el argumento como un archivo de texto para leer (comportamiento heredado de Perl).

Si la entrada estándar está vacía o no hay argumentos, no se imprime nada.

Pocos casos de prueba:

$ cat input.txt | ./myprog.rb From stdin: line 1 From stdin: line 2 $ ./myprog.rb arg1 arg2 arg3 From arguments: arg1 From arguments: arg2 From arguments: arg3 hi! From stdin: hi!


Parece que la mayoría de las respuestas están asumiendo que los argumentos son nombres de archivos que contienen contenido que debe incluirse en la entrada estándar. A continuación todo se trata como argumentos justos. Si STDIN es del TTY, entonces se ignora.

$ cat tstarg.rb while a=(ARGV.shift or (!STDIN.tty? and STDIN.gets) ) puts a end

Cualquiera de los argumentos o stdin puede estar vacío o tener datos.

$ cat numbers 1 2 3 4 5 $ ./tstarg.rb a b c < numbers a b c 1 2 3 4 5


Rápido y simple:

STDIN.gets.chomp == ''YES''


Ruby proporciona otra forma de manejar STDIN: la bandera -n. Considera que todo su programa está dentro de un bucle sobre STDIN (incluidos los archivos pasados ​​como argumentos de la línea de comandos). Ver, por ejemplo, el siguiente script de 1 línea:

#!/usr/bin/env ruby -n #example.rb puts "hello: #{$_}" #prepend ''hello:'' to each line from STDIN #these will all work: # ./example.rb < input.txt # cat input.txt | ./example.rb # ./example.rb input.txt


while STDIN.gets puts $_ end while ARGF.gets puts $_ end

Esto está inspirado en Perl:

while(<STDIN>){ print "$_/n" }