Ich habe eine einzelne Zeichenfolge, die die Befehlszeilenparameter enthält, die an eine andere ausführbare Datei übergeben werden sollen, und ich muss die Zeichenfolge [], die die einzelnen Parameter enthält, auf dieselbe Weise extrahieren wie C #, wenn die Befehle in der Befehlszeile angegeben worden wären. Die Zeichenfolge [] wird verwendet, wenn ein anderer Assembly-Einstiegspunkt über Reflektion ausgeführt wird.
Gibt es dafür eine Standardfunktion? Oder gibt es eine bevorzugte Methode (Regex?), Um die Parameter korrekt aufzuteilen? Es muss '' 'begrenzte Zeichenfolgen verarbeiten, die möglicherweise Leerzeichen enthalten, damit ich nicht einfach auf' 'teilen kann.
Beispielzeichenfolge:
string parameterString = @"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""[email protected]"" tasks:""SomeTask,Some Other Task"" -someParam foo";
Beispielergebnis:
string[] parameterArray = new string[] {
@"/src:C:\tmp\Some Folder\Sub Folder",
@"/users:[email protected]",
@"tasks:SomeTask,Some Other Task",
@"-someParam",
@"foo"
};
Ich benötige keine Befehlszeilen-Analysebibliothek, nur eine Möglichkeit, den zu generierenden String [] abzurufen.
Update : Ich musste das erwartete Ergebnis so ändern, dass es mit dem übereinstimmt, was tatsächlich von C # generiert wird (die zusätzlichen "'s in den geteilten Zeichenfolgen wurden entfernt).
quelle
Antworten:
Neben der guten und rein verwalteten Lösung von Earwicker kann der Vollständigkeit halber erwähnt werden, dass Windows auch die
CommandLineToArgvW
Funktion zum Aufteilen einer Zeichenfolge in eine Reihe von Zeichenfolgen bietet :Ein Beispiel für das Aufrufen dieser API aus C # und das Entpacken des resultierenden Zeichenfolgenarrays in verwaltetem Code finden Sie unter " Konvertieren der Befehlszeilenzeichenfolge in Args [] mithilfe der CommandLineToArgvW () - API ". Unten finden Sie eine etwas einfachere Version desselben Codes:
quelle
CommandLineToArgs("foo.exe " + commandLine).Skip(1).ToArray();
Es ärgert mich, dass es keine Funktion gibt, eine Zeichenfolge basierend auf einer Funktion zu teilen, die jedes Zeichen untersucht. Wenn ja, könnten Sie es so schreiben:
Obwohl Sie das geschrieben haben, warum nicht die notwendigen Erweiterungsmethoden schreiben? Okay, du hast mich dazu überredet ...
Erstens meine eigene Version von Split, die eine Funktion übernimmt, die entscheiden muss, ob das angegebene Zeichen die Zeichenfolge teilen soll:
Abhängig von der Situation kann es zu leeren Zeichenfolgen kommen, aber in anderen Fällen sind diese Informationen möglicherweise hilfreich, sodass ich die leeren Einträge in dieser Funktion nicht entferne.
Zweitens (und allgemeiner) ein kleiner Helfer, der ein passendes Zitatpaar vom Anfang und Ende einer Zeichenfolge abschneidet. Es ist pingeliger als die Standard-Trimmmethode - es schneidet nur ein Zeichen von jedem Ende und nicht nur von einem Ende:
Und ich nehme an, Sie möchten auch einige Tests. Na gut dann. Aber das muss absolut das Letzte sein! Zuerst eine Hilfsfunktion, die das Ergebnis der Aufteilung mit dem erwarteten Array-Inhalt vergleicht:
Dann kann ich solche Tests schreiben:
Hier ist der Test für Ihre Anforderungen:
Beachten Sie, dass die Implementierung die zusätzliche Funktion hat, Anführungszeichen um ein Argument zu entfernen, wenn dies sinnvoll ist (dank der TrimMatchingQuotes-Funktion). Ich glaube, das ist Teil der normalen Befehlszeileninterpretation.
quelle
char.IsWhiteSpace
== ' '
Der Windows-Befehlszeilenparser verhält sich genau so, wie Sie es sagen. Er wird auf den Speicherplatz aufgeteilt, es sei denn, davor steht ein nicht geschlossenes Anführungszeichen. Ich würde empfehlen, den Parser selbst zu schreiben. So etwas vielleicht:
quelle
Ich nahm die Antwort von Jeffrey L Whitledge und verbesserte sie ein wenig.
Es werden jetzt sowohl einfache als auch doppelte Anführungszeichen unterstützt. Sie können Anführungszeichen in den Parametern selbst verwenden, indem Sie andere typisierte Anführungszeichen verwenden.
Außerdem werden die Anführungszeichen aus den Argumenten entfernt, da diese nicht zur Argumentinformation beitragen.
quelle
Die gute und rein verwaltete Lösung von Earwicker konnte solche Argumente nicht verarbeiten:
Es wurden 3 Elemente zurückgegeben:
Hier ist ein Fix, um das "zitierte" Escape "-Zitat zu unterstützen:
Getestet mit 2 zusätzlichen Fällen:
Es wurde auch darauf hingewiesen, dass die akzeptierte Antwort von Atif Aziz, die CommandLineToArgvW verwendet, ebenfalls fehlgeschlagen ist. Es wurden 4 Elemente zurückgegeben:
Ich hoffe, dies hilft jemandem, der in Zukunft nach einer solchen Lösung sucht.
quelle
bla.exe aAAA"b\"ASDS\"c"dSADSD
die dazu führen,aAAAb"ASDS"cdSADSD
dass diese Lösung ausgegeben wirdaAAA"b"ASDS"c"dSADSD
. Ich könnte in Betracht ziehen, dasTrimMatchingQuotes
in a zu ändernRegex("(?<!\\\\)\\\"")
und es so zu verwenden .Environment.GetCommandLineArgs ()
quelle
Ich mag Iteratoren und heutzutage LINQ macht
IEnumerable<String>
so leicht verwendbar als Arrays von String, so mein nimmt nach dem Geist von Jeffrey L Whitledge Antwort ist (als Erweiterungsmethodestring
):quelle
In Ihrer Frage haben Sie nach einer Regex gefragt, und ich bin ein großer Fan und Benutzer von Regex. Als ich also das gleiche Argument wie Sie aufteilen musste, schrieb ich meine eigene Regex, nachdem ich herumgegoogelt und keine einfache Lösung gefunden hatte. Ich mag kurze Lösungen, also habe ich eine gemacht und hier ist sie:
Es behandelt Leerzeichen und Anführungszeichen in Anführungszeichen und konvertiert beiliegende "" in ". Verwenden Sie den Code!
quelle
Oh zum Teufel. Es ist alles ... Eugh. Aber das ist echt offiziell. Von Microsoft in C # für .NET Core, möglicherweise nur Windows, möglicherweise plattformübergreifend, aber MIT-lizenziert.
Wählen Sie Leckerbissen, Methodendeklarationen und bemerkenswerte Kommentare aus.
- -
- -
Dies ist Code, der von .NET Framework auf .NET Core portiert wird, von dem ich annehme, dass es sich entweder um die MSVC C-Bibliothek handelt oder
CommandLineToArgvW
.Hier ist mein halbherziger Versuch, einige der Spielereien mit regulären Ausdrücken zu behandeln und das Argument Null-Bit zu ignorieren. Es ist ein bisschen zauberhaft.
Habe es ein bisschen auf verrückte generierte Ausgabe getestet. Die Ausgabe entspricht einem angemessenen Prozentsatz dessen, was die Affen eingegeben und durchlaufen haben
CommandLineToArgvW
.quelle
Diesen Artikel zum Code-Projekt habe ich in der Vergangenheit verwendet. Es ist ein gutes Stück Code, aber es könnte funktionieren.
Dieser MSDN-Artikel ist das einzige, was ich finden konnte, das erklärt, wie C # Befehlszeilenargumente analysiert.
quelle
Eine rein verwaltete Lösung kann hilfreich sein. Es gibt zu viele "Problem" -Kommentare für die WINAPI-Funktion und sie ist auf anderen Plattformen nicht verfügbar. Hier ist mein Code, der ein genau definiertes Verhalten aufweist (das Sie ändern können, wenn Sie möchten).
Es sollte dasselbe tun wie .NET / Windows, wenn dieser
string[] args
Parameter bereitgestellt wird, und ich habe es mit einer Reihe von "interessanten" Werten verglichen.Dies ist eine klassische State-Machine-Implementierung, bei der jedes einzelne Zeichen aus der Eingabezeichenfolge entnommen und für den aktuellen Status interpretiert wird, wodurch eine Ausgabe und ein neuer Status erzeugt werden. Der Zustand wird in den Variablen definiert ist
escape
,inQuote
,hadQuote
undprevCh
, und der Ausgang wird in gesammeltcurrentArg
undargs
.Einige der Besonderheiten, die ich durch Experimente an einer echten Eingabeaufforderung (Windows 7) entdeckt habe:
\\
produziert\
,\"
produziert"
,""
innerhalb eines angegebenen Bereichs produziert"
.Der
^
Charakter scheint auch magisch zu sein: Er verschwindet immer, wenn er nicht verdoppelt wird. Andernfalls hat dies keine Auswirkungen auf eine echte Befehlszeile. Meine Implementierung unterstützt dies nicht, da ich in diesem Verhalten kein Muster gefunden habe. Vielleicht weiß jemand mehr darüber.Etwas, das nicht in dieses Muster passt, ist der folgende Befehl:
Der
cmd
Befehl scheint die äußeren Anführungszeichen zu erfassen und den Rest wörtlich zu nehmen. Darin muss eine spezielle magische Sauce sein.Ich habe keine Benchmarks für meine Methode durchgeführt, halte sie jedoch für relativ schnell. Es verwendet
Regex
keine Verkettung von Zeichenfolgen und führt keine Verkettung durch, sondern verwendet aStringBuilder
, um die Zeichen für ein Argument zu sammeln und sie in eine Liste aufzunehmen.quelle
Verwenden:
Basierend auf Vapor in der Antwort der Alley unterstützt diese auch ^ Escape.
Beispiele:
Es werden auch mehrere Leerzeichen unterstützt (Argumente werden nur einmal pro Leerzeichenblock unterbrochen).
quelle
Derzeit ist dies der Code, den ich habe:
Es funktioniert nicht mit maskierten Anführungszeichen, aber es funktioniert für die Fälle, auf die ich bisher gestoßen bin.
quelle
Dies ist eine Antwort auf Antons Code, der nicht mit maskierten Anführungszeichen funktioniert. Ich habe 3 Stellen geändert.
quelle
Ich glaube nicht, dass es einfache Anführungszeichen oder Anführungszeichen für C # -Anwendungen gibt. Die folgende Funktion funktioniert gut für mich:
quelle
Sie können sich den Code ansehen, den ich gestern gepostet habe:
[C #] Pfad- und Argumentzeichenfolgen
Es teilt einen Dateinamen + Argumente in string [] auf. Kurze Pfade, Umgebungsvariablen und fehlende Dateierweiterungen werden behandelt.
(Ursprünglich war es für UninstallString in Registry.)
quelle
Versuchen Sie diesen Code:
Es ist in Portugiesisch geschrieben.
quelle
posicao_ponteiro += ((fim - posicao_ponteiro)+1);
.Hier ist ein Einzeiler, der die Arbeit erledigt (siehe die eine Zeile, die die gesamte Arbeit innerhalb der BurstCmdLineArgs (...) -Methode erledigt).
Nicht das, was ich als die am besten lesbare Codezeile bezeichnen würde, aber Sie können sie aus Gründen der Lesbarkeit ausbrechen. Es ist absichtlich einfach und funktioniert nicht für alle Argumentfälle (wie Dateinamenargumente, die das Trennzeichen für geteilte Zeichenfolgen enthalten).
Diese Lösung hat in meinen Lösungen, die sie verwenden, gut funktioniert. Wie ich bereits sagte, wird die Aufgabe ohne das Code-Nest einer Ratte erledigt, um jedes mögliche Argumentformat n-Fakultät zu verarbeiten.
quelle
Ich konnte hier nichts finden, was mir gefallen hat. Ich hasse es, den Stapel mit Ertragsmagie für eine kleine Befehlszeile durcheinander zu bringen (wenn es ein Terabyte-Stream wäre, wäre es eine andere Geschichte).
Hier ist meine Meinung, es unterstützt Anführungszeichen mit doppelten Anführungszeichen wie diesen:
Ergebnis:
quelle
Ich habe State Machine so implementiert, dass dieselben Parser-Ergebnisse erzielt werden, als würden Argumente an die .NET-Anwendung übergeben und in der
static void Main(string[] args)
Methode verarbeitet .quelle
Hier ist die Lösung, die Leerzeichen (einzelne oder mehrere Leerzeichen) als Trennzeichen für Befehlszeilenparameter behandelt und die tatsächlichen Befehlszeilenargumente zurückgibt:
quelle
Ich bin mir nicht sicher, ob ich dich verstanden habe, aber ist das Problem, dass das als Splitter verwendete Zeichen auch im Text zu finden ist? (Abgesehen davon wird es mit double "?"
In diesem
for
Fall würde ich eine Schleife erstellen und alle Instanzen, in denen <"> vorhanden ist, durch <|> (oder ein anderes" sicheres "Zeichen) ersetzen, aber sicherstellen, dass nur <"> und nicht <""> ersetzt wirdNach dem Iterieren der Zeichenfolge würde ich wie zuvor angegeben die Zeichenfolge teilen, jetzt jedoch das Zeichen <|>.
quelle
Ja, das Zeichenfolgenobjekt verfügt über eine integrierte Funktion namens
Split()
, die einen einzelnen Parameter verwendet, der das zu suchende Zeichen als Trennzeichen angibt, und ein Array von Zeichenfolgen (Zeichenfolge []) mit den einzelnen Werten zurückgibt.quelle