2016-06-23 7 views
2

Boost.Program_options를 사용하여 strace과 같은 접두사 프로그램을 작성하고 싶습니다. 접두사는 내 프로그램이 다른 임의의 앞에 놓이는 것을 의미합니다. command [args]. 따라서 내 프로그램은 정의 된 키워드 인수/플래그를 수락해야합니다. 첫 번째 위치 인수는 내가 접두어로 붙인 명령을 나타냅니다. 이 명령 자체는 내가 모르는 매개 변수 조합과 내 프로그램의 매개 변수와 겹칠 수도 있습니다. 그것에서 끝나야 다음에 오는 따라서 첫 번째 위치 인수 및 아무거나 std::vector<std::string> :Boost.Program_options로 접두어 명령을 작성하십시오.

는 올바른 사용법 먼저 기본적으로 올바른 형태로 정의 된 키워드 중 하나를 지정하는 것입니다
./foo --bar 13 command1      # Should run fine 
./foo command2 positional     # Should run fine 
./foo --bar 13 command3 --unknown argument # Should run fine 
./foo --unknown command4      # should fail 
./foo --bar 13 command5 --bar 42    # Should work but set bar to 13 
./foo command6 --bar 42      # Should not set bar at all 
./foo --bar 13 -- command7 --bar 42 --unknown argument  # Should work 

, 첫째가 있습니다 내 사전 정의 된

내가 시도 두 가지 방법의 수해야 정의 :

1) allow_unregistered 사용 :

#include <iostream> 
#include <boost/program_options.hpp> 

namespace po = boost::program_options; 

int main(int argc, const char** argv) 
{ 
    int bar = 0; 
    po::options_description desc("Allowed options"); 

    desc.add_options() 
      ("bar", po::value(&bar), "bar"); 


    po::variables_map vm; 
    po::parsed_options parsed = 
     po::command_line_parser(argc, argv).options(desc).allow_unregistered().run(); 
    po::store(parsed, vm); 
    po::notify(vm); 

    auto command = po::collect_unrecognized(parsed.options, po::include_positional); 
    std::cout << "bar: " << bar << ", command:"; 
    for (const auto& c : command) std::cout << " " << c; 
    std::cout << std::endl; 
} 

이 명령 4,5,6

2)이 명령 3,5,6 실패 무제한 발생

std::vector<std::string> command; 

desc.add_options() 
     ("bar", po::value(&bar), "bar") 
     ("command", po::value(&command)); 

po::positional_options_description p; 
p.add("command", -1); 

po::variables_map vm; 
po::parsed_options parsed = 
    po::command_line_parser(argc, argv).options(desc).positional(p).run(); 
po::store(parsed, vm); 
po::notify(vm); 

함께 한 위치 옵션을 실패합니다.

+0

자세한 내용을 자세히 설명하고 어떤 조합을 허용해야하는지, 허용하지 않는지,이 7 가지 예에서는 분명하지 않습니다. – alexeykuzmin0

+0

@ alexeykuzmin0 내 업데이트를 참조하십시오. "접두사는 내 프로그램이 다른 임의의 것 'command [args]'. 따라서 내 프로그램은 정의 된 여러 개의 키워드 인수/플래그를 받아 들여야합니다. 첫 번째 위치 인수는 접두어로 붙이는 명령을 나타냅니다.이 명령 뒤에는 내가하는 매개 변수의 조합이 올 수 있습니다 알지 못하고 내 프로그램의 매개 변수와 겹칠 수도 있습니다. 따라서이 첫 번째 위치 인수와 그 이후에 오는 모든 것은'std :: vector ' "에 있어야합니다. 예제는 특정 코너 케이스를 나타냅니다. – Zulan

+0

인수에 공백이 포함될 수 있습니까? 그런 경우에 논쟁이 ""에 있습니까? – alexeykuzmin0

답변

2

패치를 포함하여 Boost Trac에서 이에 대한 기능 요청이 있습니다 : https://svn.boost.org/trac/boost/ticket/6991. 티켓에는 많은 움직임이 없었지만 패치는 여전히 Boost에 적용됩니다 (최신 버전 인 1.61.0 기준).

빌드 시스템에서 허용하는 경우 Boost의 로컬 복사본에 패치를 적용 할 수 있습니다. 그렇지 않으면 boost::program_options::detail::cmdlinecmdline.hpp, detail/cmdline.hppcmdline.cpp에서 자신의 네임 스페이스에 추출하고 해당 구성 요소를 패치하고 boost::program_options::cmdline 대신 패치 된 구성 요소를 사용할 수 있습니다.

또 하나의 옵션은 extra_style_parser 매개 변수를 사용하여, boost::program_options::detail::cmdline의 동작을 해킹하는 것입니다

po::detail::cmdline cmdline(argc, argv); 
cmdline.set_options_description(desc); 
cmdline.set_positional_options(p); 
std::vector<po::detail::cmdline::style_parser> style_parsers{ 
    [&](auto& args) { return cmdline.parse_long_option(args); }, 
    [&](auto& args) { return cmdline.parse_short_option(args); }}; 
cmdline.extra_style_parser([&](std::vector<std::string>& args) { 
    auto const current_size = args.size(); 
    std::vector<po::option> result; 
    for (auto const& parser : style_parsers) { 
     auto const next = parser(args); 
     result.insert(result.end(), next.begin(), next.end()); 
     if (args.size() != current_size) 
      return result; 
    } 
    if (args.size() && args[0] != "--") args.insert(args.begin(), "--"); 
    auto const next = cmdline.parse_terminator(args); 
    result.insert(result.end(), next.begin(), next.end()); 
    return result; 
}); 
po::parsed_options parsed{&desc}; 
parsed.options = cmdline.run(); 
po::store(parsed, vm); 
po::notify(vm); 

Example. 경고 : 문서화되지 않은 라이브러리 내부가 해킹되어 언제든지 중단 될 수 있습니다.

+0

정확히 내가 필요로하는 것 같습니다. 이 패치가 결코 벗겨지지 않는 것을 보니 슬픈 일입니다. 그것이 저를 위해 작동하는지 나는 볼 것이다. – Zulan