Ich habe die folgende Frage auf SO gepostet, aber ich denke, ich boost::program_options
kann mir hier nicht helfen:
Ich habe Optionen
--foo
(Kurzform-f
) und--bar
die einer besonderen Behandlung bedürfen, sie sind wiederholbar und die Reihenfolge sollte eine Rolle spielen. Also für folgendes:program --foo 1 --z -f 2 --bar 3 --x --foo 4
Ich möchte eine Key-Value-Map erstellen, die ich erstellen kann
[("foo", 1), ("foo", 2), ("bar", 3), ("foo", 4)]
.Bitte beachten Sie die Reihenfolge dieses Arrays von Tupeln, sie ist dieselbe wie in der Befehlszeile. Ich habe unwichtige Optionen im Array verworfen, aber sie können trotzdem in der Befehlszeile vorhanden sein.
Es scheint, dass der einzige Weg, wiederholbare Optionen zuzulassen, darin
boost::program_options
besteht, eine bestimmte Option aufzurufencomposing()
, aber dann, da jede alle ihre Werte in einem Vektor speichert, verliere ich die Reihenfolge, die ich zum Verschachteln von Optionen benötige.Also, kann
boost::program_options
dabei helfen?
Quelle: https://stackoverflow.com/questions/36973114/
Ich suche nach einer Bibliothek, mit der ich die geparsten Optionen (wenn möglich mit ihren auf ihre langen oder kurzen Namen normalisierten Namen) in der Reihenfolge durchsuchen kann, die in der Befehlszeile angegeben ist, da eine solche Reihenfolge für mich wichtig ist.
Verwenden des neuesten Masters in CLI11 (wird in Version 1.1 sein) (jetzt auch ein offizielles Beispiel):
#include <CLI/CLI.hpp>
#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
int main(int argc, char **argv) {
CLI::App app;
std::vector<int> foos;
auto foo = app.add_option("--foo,-f", foos);
std::vector<int> bars;
auto bar = app.add_option("--bar", bars);
app.add_flag("--z,--x"); // Random other flags
try {
app.parse(argc, argv);
} catch(const CLI::ParseError &e) {
return app.exit(e);
}
// I perfer using the back and popping
std::reverse(std::begin(foos), std::end(foos));
std::reverse(std::begin(bars), std::end(bars));
std::vector<std::pair<std::string, int>> keyval;
for(auto option : app.parse_order()) {
if(option == foo) {
keyval.emplace_back("foo", foos.back());
foos.pop_back();
}
if(option == bar) {
keyval.emplace_back("bar", bars.back());
bars.pop_back();
}
}
// Prove the vector is correct
for(auto &pair : keyval) {
std::cout << pair.first << " : " << pair.second << std::endl;
}
}
Ausgabe:
./examples/inter_argument_order --foo 1 --z -f 2 --bar 3 --x --foo 4
foo : 1
foo : 2
bar : 3
foo : 4
Verwenden von Poco, das einen Rückruf pro Flag aufruft, in der folgenden Reihenfolge:
#include <iostream>
#include <Poco/Util/Option.h>
#include <Poco/Util/OptionSet.h>
#include <Poco/Util/Application.h>
#include <Poco/Util/HelpFormatter.h>
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::Application;
using Poco::Util::HelpFormatter;
using Poco::Util::OptionCallback;
struct SampleApp : Application {
void defineOptions(OptionSet &options) {
Application::defineOptions(options);
options.addOption(Option("help", "h", "display help information")
.required(false)
.repeatable(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleHelp)));
options.addOption(Option("foo", "f", "foo option")
.required(false)
.repeatable(true)
.argument("<foo>")
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("bar", "b", "bar option")
.required(false)
.repeatable(false)
.argument("<bar>")
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("z", "", "z option")
.required(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
options.addOption(Option("x", "", "x option")
.required(false)
.callback(OptionCallback<SampleApp>(
this, &SampleApp::handleOptions)));
}
void handleHelp(const std::string &, const std::string &) {
helpRequested = true;
displayHelp();
stopOptionsProcessing();
}
void handleOptions(const std::string &name, const std::string &value) {
std::cout << name << " " << value << std::endl;
}
void displayHelp() {
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("<options>");
helpFormatter.setHeader("Foo/Bar options.");
helpFormatter.format(std::cout);
}
bool helpRequested = false;
};
POCO_APP_MAIN(SampleApp)
❯❯❯ ./sample --help
usage: sample <options>
Foo/Bar options.
-h, --help display help information
-f<foo>, --foo=<foo> foo option
-b<bar>, --bar=<bar> bar option
--z z option
--x x option
❯❯❯ ./sample --foo 1 --z -f 2 --bar 3 --x --foo 4
foo 1
z
foo 2
bar 3
x
foo 4
einpoklum
program_options
Ihnen das alles geben kann, was es nicht selbst alsvector<string>
. Tatsächlich verwende ich dieses hässliche Stück Code , um es in eine Schlüsselwertkarte in einem Projekt einzufügen, an dem ich arbeite, und es sollte nicht schwierig sein, es an das anzupassen, was Sie brauchen, denke ich.einpoklum
boost::program_options::collect_unrecognized()
. Obwohl ich sagen werde, dass Sie wahrscheinlich keine Reihenfolge für Befehlszeilenoptionen annehmen sollten, dh das Problem liegt eher in der Tatsache, dass Sie versuchen, dies IMO zu tun.oblitum
matrix_product_program --matrix="{...}" --matrix="{...}" --matrix="{...}"
. Irgendein Problem damit, diese Situation mit einer Lösung wie erklärt anzupassen?einpoklum
boost::program_options
interessant ist.oblitum
oblitum
oblitum
collect_unrecognized
und des von Ihnen gesendeten Ausschnitts ... Es sieht nicht so gut aus, wie ich erwartet hatte. Sehen Sie, dass ich sogar erwähnt habe, dass Optionsnamen normalisiert wurden (was bedeutet, dass sie erkannt wurden), verbunden mit entsprechenden Werten.einpoklum