Je veux traiter de l'entrée de ligne de commande dans Ruby:
> cat input.txt | myprog.rb
> myprog.rb < input.txt
> myprog.rb arg1 arg2 arg3 ...
Quelle est la meilleure façon de le faire? En particulier, je souhaite traiter avec STDIN vierge et j'espère une solution élégante.
#!/usr/bin/env Ruby
STDIN.read.split("\n").each do |a|
puts a
end
ARGV.each do |b|
puts b
end
Voici certaines choses que j'ai trouvées dans ma collection de Ruby obscure.
Ainsi, en Ruby, une simple implémentation sans sonneries de la commande Unix cat
serait:
#!/usr/bin/env Ruby
puts ARGF.read
ARGF
est votre ami en matière de saisie; c'est un fichier virtuel qui obtient toutes les entrées des fichiers nommés ou 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
Heureusement, nous n’avons pas trouvé de diamantaire à Ruby, mais nous avons eu ARGF
en remplacement. Bien qu'obscur, cela s'avère en fait utile. Considérez ce programme, qui ajoute des en-têtes de droits d'auteur sur place (grâce à un autre Perlism, -i
) à chaque fichier mentionné sur la ligne de commande:
#!/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édit à:
Ruby fournit un autre moyen de gérer STDIN: l'indicateur -n. L'ensemble de votre programme est traité comme une boucle sur STDIN (y compris les fichiers transmis en tant qu'arguments en ligne de commande). Voir par exemple le script 1 ligne suivant:
#!/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
Je ne suis pas tout à fait sûr de ce dont vous avez besoin, mais je voudrais utiliser quelque chose comme ceci:
#!/usr/bin/env Ruby
until ARGV.empty? do
puts "From arguments: #{ARGV.shift}"
end
while a = gets
puts "From stdin: #{a}"
end
Notez que comme le tableau ARGV est vide avant la première gets
, Ruby n'essaiera pas d'interpréter les arguments en tant que fichier texte à lire (comportement hérité de Perl).
Si stdin est vide ou s'il n'y a pas d'argument, rien n'est imprimé.
Quelques cas de test:
$ 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!
Quelque chose comme ça peut-être?
#/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
Exemple:
> 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
while STDIN.gets
puts $_
end
while ARGF.gets
puts $_
end
Ceci est inspiré par Perl:
while(<STDIN>){
print "$_\n"
}
Il semble que la plupart des réponses supposent que les arguments sont des noms de fichiers contenant du contenu à cataloguer sur le stdin. Ci-dessous, tout est traité comme de simples arguments. Si STDIN provient du TTY, il est ignoré.
$ cat tstarg.rb
while a=(ARGV.shift or (!STDIN.tty? and STDIN.gets) )
puts a
end
Les arguments ou stdin peuvent être vides ou contenir des données.
$ cat numbers
1
2
3
4
5
$ ./tstarg.rb a b c < numbers
a
b
c
1
2
3
4
5
Je fais quelque chose comme ça:
all_lines = ""
ARGV.each do |line|
all_lines << line + "\n"
end
puts all_lines
J'ajouterai que pour utiliser ARGF
avec des paramètres, vous devez effacer ARGV
avant d'appeler ARGF.each
. En effet, ARGF
traitera tout ce qui est dans ARGV
comme un nom de fichier et lira les lignes à partir de là.
Voici un exemple d'implémentation 'tee':
File.open(ARGV[0], 'w') do |file|
ARGV.clear
ARGF.each do |line|
puts line
file.write(line)
end
end
Simple et rapide:
STDIN.gets.chomp == 'YES'