3

フラットな json ドキュメントを生成するコマンド ライン ツールがあります。これを想像してください:

$ ruby gen-json.rb --foo bar --baz qux
{
    "foo": "bar"
    "baz": "qux"
}

私が欲しいのは、これが機能することです:

$ ruby gen-json.rb --foo $'\0' --baz qux
{
    "foo": null,
    "baz": "qux"
}

null の代わりに空の文字列を取得します。問題をさらに単純化するには、次のことを考慮してください。

$ cat nil-args.rb
puts "argv[0] is nil" if ARGV[0].nil?
puts "argv[0] is an empty string" if ARGV[0] == ""
puts "argv[1] is nil" if ARGV[1].nil?

このように実行して、この出力を取得したい:

$ ruby nil-args.rb $'\0' foo
argv[0] is nil

しかし、代わりに私は得る

argv[0] is an empty string

これは (ほぼ間違いなく) Ruby インタープリターのバグだと思います。argv[0] を null で終了する C 文字列として扱っています。

4

4 に答える 4

3

コマンド ライン引数は常に文字列です。別の方法で処理したい引数を示すために、センチネルを使用する必要があります。

于 2012-05-03T20:31:44.520 に答える
1

あなたが提案していることを文字通り実行できないと確信しています。これは、使用しているシェルの基本的な制限です。文字列引数のみをスクリプトに渡すことができます。

コメントで既に言及されていますが、試した \0 メソッドで得られる出力は完全に理にかなっています。null ターミネータは技術的には空の文字列です。

また、まだ定義されていない配列の要素にアクセスすると、常に nil になることも考慮してください。

a = [1, 2, 3]
a[10].nil?
#=> true

ただし、可能な解決策は、プログラムが次のように機能することです。

$ ruby gen-json.rb --foo --baz qux
{
    "foo": null,
    "baz": "qux"
}

したがって、2 つのマイナス記号の引数の後に別の 2 つのマイナス記号の引数がある場合、最初の引数が null であると推測します。ただし、これを実現するには、独自のコマンド ライン オプション パーサーを作成する必要があります。

これは非常に単純なサンプル スクリプトで、動作しているように見えます (ただし、エッジ ケースやその他の問題が発生する可能性があります)。

require 'pp'

json = {}

ARGV.each_cons(2) do |key, value|
  next unless key.start_with? '--'
  json[key] = value.start_with?('--') ? nil : value
end

pp json

それはあなたの目的のために働くでしょうか?:)

于 2012-05-04T00:35:52.667 に答える
0

nil を意味する特殊文字を決定する必要があります。私はお勧めします(二重引用符は、リテラル文字列のバックスラッシュゼロが渡される"\0"ことを保証します)。次に、特別な型コンバーターを で使用できます。OptionParser

require 'optparse'
require 'json'

values = {}
parser = OptionParser.new do |opts|
  opts.on("--foo VAL",:nulldetect) { |val| values[:foo] = val }
  opts.on("--bar VAL",:nulldetect) { |val| values[:foo] = val }

  opts.accept(:nulldetect) do |string|
    if string == '\0'
      nil
    else
      string
    end
  end
end

parser.parse!

puts values.to_json

明らかに、これには受け入れるフラグについて明示する必要がありますが、フラグを受け入れたい場合は、ifチェックのためにステートメントを手で詰め込むことができます"\0"

補足として、フラグをオプションにすることができますが、空の文字列がブロックに渡されます。

opts.on("--foo [VAL]") do |val|
  # if --foo is passed w/out args, val is empty string
end

だから、あなたはまだ代役が必要です

于 2012-05-09T12:25:17.427 に答える
0

Ruby は と 以外のすべてnilfalseとして扱いtrueます。0したがって、空の文字列はすべて true (およびor )として評価されます0.0

次のようなものを使用することで、nil 動作を強制できます。

ARGV.map! do |arg|
  if arg.empty?
    nil
  else
    arg
  end
end

このように、空の文字列は への参照に変換されnilます。

于 2012-05-03T20:59:33.990 に答える