2010-10-17 5 views
2

J'ai écrit un script simple qui écrit tous les arguments donnés dans un seul fichier texte, séparé par newline. Je voudrais lui passer une liste de fichiers en utilisant OptionParser. Je voudrais ajouter quelques fichiers en utilisant des caractères génériques comme /dir/*.Analyse des arguments de ligne de commande en tant que caractères génériques

J'ai essayé ceci:

opts = OptionParser.new 
opts.on('-a', '--add FILE') do |s| 
    puts "DEBUG: before #{s}" 
    @options.add = s 
    puts "DEBUG: after #{@options.add}" 
end 
... 
def process_arguments 
    @lines_to_add = Dir.glob @options.add 
end 

Put quand j'ajouter des fichiers comme ceci:

./script.rb -a /path/* 

Je reçois toujours que le premier fichier dans le répertoire. Toutes les sorties de débogage montrent seulement le premier fichier de répertoire, et il semble que OptionParser fait quelques interprétations magiques

Est-ce que quelqu'un sait comment manipuler ceci?

Répondre

4

Vous n'avez pas mentionné quel système d'exploitation que vous utilisez (il importe). Sous Windows, tout ce que vous tapez sur la ligne de commande est transmis au programme sans modification. Donc, si vous tapez

./script.rb -a /path/* 

alors les arguments du programme contiennent "-a" et "/path/*".

Sous Unix et d'autres systèmes avec des shells similaires, le shell développe argument expansion qui développe automatiquement les caractères génériques dans la ligne de commande. Ainsi, lorsque vous tapez la même commande ci-dessus, le shell recherche les fichiers dans le répertoire /path/* et développe les arguments de ligne de commande avant l'exécution de votre programme. Les arguments de votre programme peuvent donc être "-a", "/path/file1" et "/path/file2".

Un point important est que le script ne peut pas savoir si l'expansion des arguments s'est produite ou si l'utilisateur a réellement tapé tous ces noms sur la ligne de commande.

+1

L'implication ici est qu'un programme Ruby doit faire son propre globbing sous Windows. Pas vrai, sur Windows Ruby globs arguments de ligne de commande automagically. Voir win32.c. – cdarke

0

Ce qui se passe, c'est que le shell étend le caractère générique avant que Ruby n'y arrive. Alors, vraiment vous traitez:

./script.rb -a /path/file1 /path/file2 ...... 

mettre des guillemets autour /path/* pour éviter l'expansion de la coquille et passer le générique à Ruby:

./script.rb -a '/path/*' 
0

Le shell étend l'argument avant qu'il ne soit transmis à votre programme. Continuez à consommer les noms de fichiers jusqu'à ce que vous atteigniez une autre option, ou demandez à l'utilisateur d'échapper les caractères génériques (par exemple ./script.rb -a '/path/*') et de les regrouper vous-même.

3

Comme mentionné ci-dessus, la ligne de commande est en cours d'analyse avant que le système d'exploitation ne passe la commande à Ruby. Le caractère générique est en cours de développement dans une liste de noms de fichiers délimités par des espaces.

Vous pouvez voir ce qui se passera si vous tapez quelque chose comme echo * à la ligne de commande, puis, au lieu de frapper Retour, au lieu touché Esc puis *. Vous devriez voir le * développé dans la liste des fichiers correspondants.

Après avoir appuyé sur Retourne ces noms seront ajoutés à la matrice ARGV. OptionParser va parcourir ARGV et trouver les drapeaux que vous avez définis, récupérer les éléments suivants si nécessaire, puis les retirer de ARGV. Lorsque OptionParser est terminé, tous les éléments ARGV qui ne rentrent pas dans les options restent dans le tableau ARGV où vous pouvez les atteindre. Dans votre code, vous recherchez un seul paramètre pour l'option '-a' ou '--add FILE'. OptionParser a une option Array qui va récupérer les éléments séparés par des virgules à partir de la ligne de commande mais qui seront ensuite séparés par des espaces.

require 'optparse' 

options = [] 
opts = OptionParser.new 
opts.on('-a', '--add FILE', Array) do |s| 
    options << s 
end.parse! 

print "options => ", options.join(', '), "\n" 
print "ARGV => ", ARGV.join(', '), "\n" 

Enregistrer que dans un fichier et essayez votre ligne de commande avec -a one two three, puis avec -a one,two,three. Vous verrez comment l'option Array saisit les éléments différemment selon qu'il y a des virgules ou des espaces entre les paramètres. Étant donné que le caractère générique * est remplacé par des noms de fichiers délimités par des espaces, vous devrez post-traiter ARGV après l'exécution d'OptionParser, ou globaliser par programme le répertoire et créer la liste de cette manière. ARGV a tous les fichiers à l'exception de celui récupéré dans l'option -a donc, personnellement, je laisserais tomber l'option -a et laisserais ARGV contenir tous les fichiers.

Vous devrez globaliser le répertoire si * a trop de fichiers et dépasse la taille du tampon. Vous saurez si cela se produit parce que l'OS va se plaindre.

+0

si la ligne de commande est 'ruby test.rb --noms abc def efi ghi --places london dublin paris' Comment traiter cette liste pour obtenir tous les noms et les lieux dans un tableau? – nimish

+0

C'est une question totalement distincte, et doit être posée en tant que telle, pas comme commentaire. Assurez-vous de fournir votre code en essayant de résoudre le problème et d'afficher un exemple du format de données que vous souhaitez créer. –

Questions connexes