2

与えられたすべての引数を改行で区切って単一のテキスト ファイルに書き込む簡単なスクリプトを作成しました。OptionParser を使用してファイルのリストを渡したいと思います。のようなワイルドカードを使用して、いくつかのファイルを追加したいと思います/dir/*

私はこれを試しました:

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

次のようなファイルを追加すると、次のようになります。

./script.rb -a /path/*

私は常にディレクトリ内の最初のファイルのみを取得します。すべてのデバッグ出力は、ディレクトリの最初のファイルのみを示しており、OptionParser が何らかの魔法の解釈を行っているように見えます。

誰もこれを処理する方法を知っていますか?

4

4 に答える 4

4

使用しているオペレーティング システムについて言及していませんでした (重要です)。

Windows では、コマンド ラインに入力したものはすべて変更されずにプログラムに渡されます。したがって、入力すると

./script.rb -a /path/*

その場合、プログラムへの引数には と が含まれ"-a"ます"/path/*"

Unix および同様のシェルを備えたその他のシステムでは、シェルは、コマンド ラインでワイルドカードを自動的に展開する引数展開を行います。したがって、上記と同じコマンドを入力すると、シェルはディレクトリ内のファイルを探して/path/*、プログラムを実行する前にコマンド ライン引数を展開します。したがって、プログラムへの引数は、、、および となる可能性があり"-a"ます。"/path/file1""/path/file2"

重要な点は、スクリプトは、引数の展開が発生したかどうか、またはユーザーがコマンド ラインでこれらすべてのファイル名を実際に入力したかどうかを判断できないことです。

于 2010-10-17T19:03:03.020 に答える
3

前述のように、OS がコマンドを Ruby に渡す前にコマンドラインが解析されます。ワイルドカードは、スペースで区切られたファイル名のリストに展開されています。

echo *コマンドラインで次のように入力すると、 を押す代わりに then をReturn押すEscとどうなるかがわかります**一致するファイルのリストが展開されて表示されるはずです。

これらの名前をヒットした後Return、ARGV 配列に追加されます。OptionParser は ARGV を調べて、定義したフラグを見つけ、必要に応じて次の要素を取得し、ARGV から削除します。OptionParser が終了すると、オプションに適合しなかった ARGV 要素は、それらを取得できる ARGV 配列に残ります。

'-a'コードでは、 or'--add FILE'オプションの単一のパラメーターを探しています。OptionParser にはArray、コマンド ラインからコンマ区切りの要素を取得するオプションがありますが、後続のスペース区切りの要素も取得します。

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"

それをファイルに保存し、コマンドラインを-a one two three、次に で試してください-a one,two,three。パラメータ間にコンマまたはスペースがあるかどうかに応じて、オプションがどのようにArray異なる方法で要素を取得するかがわかります。

ワイルドカードはスペースで区切られたファイル名に置き換えられるため、*OptionParser を実行した後に ARGV を後処理するか、プログラムでディレクトリをグロブしてリストを作成する必要があります。ARGV には、-aオプションで選択されたものを除くすべてのファイルが含まれているため、個人的には、-aオプションを削除して、ARGV にすべてのファイルを含めます。

*ファイルが多すぎてバッファサイズを超える場合は、ディレクトリをグロブする必要があります。OSが文句を言うので、それが起こるかどうかがわかります。

于 2010-10-17T23:37:59.337 に答える
0

何が起こっているかというと、Ruby がワイルドカードに到達する前にシェルがワイルドカードを展開しているということです。だから本当にあなたは処理しています:

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

シェルの展開を避けるために引用符を付け/path/*て、ワイルドカードを Ruby に渡します。

./script.rb -a '/path/*'
于 2010-10-17T19:02:55.473 に答える
0

シェルは、プログラムに渡される前に引数を展開しています。別のオプションに到達するまでファイル名を消費し続けるか、ユーザーにワイルドカード (例: ./script.rb -a '/path/*') をエスケープさせて自分でグロブしてもらいます。

于 2010-10-17T19:03:05.953 に答える