2012-05-03 2 views
3

플랫 json 문서를 생성하는 명령 행 도구가 있습니다. 이 상상 :명령 줄 args에 nil을 지정하십시오.

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

내가 원하는 것은이 작업을하는 것입니다

대신 널 (null)의
$ ruby gen-json.rb --foo $'\0' --baz qux 
{ 
    "foo": null, 
    "baz": "qux" 
} 

나는 빈 문자열을 얻을. 문제를 단순화하기 위해 더욱이 고려 :

$ 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 

나는이 의심 (틀림없이) 루비 인터프리터의 버그. argv [0]을 C 문자열로 처리하여 null이 종료됩니다.

+0

추신 필요 했어 perl은 같은 방법으로 동작합니다 – jaybuff

+0

ASCII에서 char 번호가 0 인 문자열이 빈 문자열이기 때문에? –

+2

ASCII 코드 0은 C가 문자열 배열을 종료하는 데 사용하는 NUL입니다. 그래서 당신은 C - 문자열에 NUL을 가질 수 없습니다. 나는 루비 인터프리터가 문자열을 읽어야한다고 제안하고 그것이 단지 NUL이면 var를 nil로 설정한다. ARGV [0]의 유형이 더 이상 String이 아니기 때문에 아마 여러 가지 문제가 발생할 수 있습니다. 그래서 나는 내가 원하는 것이 가능하다고 생각하지 않는다. – jaybuff

답변

3

명령 줄 인수는 항상 문자열입니다. 그렇지 않으면 치료할 인자를 나타내는 데 센티널을 사용해야합니다.

+0

한 문자 (NUL 문자)가 포함 된 문자열 일 수는 없습니까? – jaybuff

+0

문제는 C 레벨에서 NUL이 보이지 않기 때문에 Ruby에서 보이지 않는다는 것입니다. –

0

루비는 nilfalse을 제외한 모든 것을, true으로 취급합니다. 따라서 빈 문자열이면 true로 평가됩니다 (0 또는 0.0).

이 뭔가를 가진하여 전무 행동을 강제 할 수

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

이 방법은 빈 문자열은 nil에 대한 참조를 변환 할 것입니다.

+0

nil과 빈 문자열을 구별 할 수 있기를 원합니다. – jaybuff

+0

그러면 문제가있는 곳을 볼 수 없습니다. 기본적으로'nil'과 빈 문자열을 구별합니다 (빈 문자열을 인수로 전달할 때'nil'으로 평가되지 않습니다). 그러나 분명히 원하는 것은 NOT입니다. 해. 정확히 ** ** ** 원하는 경우 빈 문자열을 'nil'에 매핑하고 ** ** 빈 문자열을 그대로 취급 하시겠습니까? –

+0

NUL이 포함 된 A (루비) 문자열이 빈 문자열과 다릅니다. – jaybuff

1

나는 정말로 당신이 당신이 제안하고있는 것을 할 수 없다고 확신합니다. 사용중인 셸의 근본적인 제한 사항입니다. 문자열 인수는 스크립트에만 전달할 수 있습니다.

이미 주석에 언급되어 있지만 \ 0 방법으로 얻은 결과는 완벽합니다. null 종결자가 기술적으로 빈 문자열입니다.

아직 정의되지 않은 배열의 요소에 액세스하면 항상 0이됩니다. 프로그램은 다음과 같이 작동하려면

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

가능한 솔루션은, 그러나, 다음과 같습니다 그래서

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

를 다른 이중 빼기 기호 인수에 이어 더블 빼기 기호 인수가있을 때, 당신은 유추 첫번째 것은 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 

겠습니까 당신의 목적을 위해 그 일?:)

0

당신은 nil을 의미하는 특수 문자를 결정해야 할 것입니다. "\0" (큰 따옴표는 리터럴 문자열 백 슬래시 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 

그래서, 당신은 여전히 ​​독립에