Dividi la stringa contenente i parametri della riga di comando nella stringa in C #

Ho una singola stringa che contiene i parametri della riga di comando da passare a un altro eseguibile e ho bisogno di estrarre la stringa [] contenente i singoli parametri nello stesso modo in cui C # sarebbe se i comandi fossero stati specificati sulla riga di comando. La stringa [] verrà utilizzata quando si esegue un punto di ingresso di un altro assieme tramite riflessione.

Esiste una funzione standard per questo? O c’è un metodo preferito (regex?) Per dividere correttamente i parametri? Deve gestire stringhe “” delimitate che possono contenere spazi correttamente, quindi non posso dividere semplicemente “”.

Stringa di esempio:

string parameterString = @"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""[email protected]"" tasks:""SomeTask,Some Other Task"" -someParam foo"; 

Esempio di risultato:

 string[] parameterArray = new string[] { @"/src:C:\tmp\Some Folder\Sub Folder", @"/users:[email protected]", @"tasks:SomeTask,Some Other Task", @"-someParam", @"foo" }; 

Non ho bisogno di una libreria di analisi della riga di comando, solo un modo per ottenere la stringa [] che dovrebbe essere generata.

    Aggiornamento : ho dovuto modificare il risultato previsto per abbinare ciò che è effettivamente generato da C # (rimosso gli “extra” nelle stringhe divise)

    Oltre alla buona e pura soluzione gestita da Earwicker , potrebbe essere utile ricordare, per completezza, che Windows fornisce anche la funzione CommandLineToArgvW per suddividere una stringa in una serie di stringhe:

     LPWSTR *CommandLineToArgvW( LPCWSTR lpCmdLine, int *pNumArgs); 

    Analizza una stringa della riga di comando Unicode e restituisce una serie di puntatori agli argomenti della riga di comando, insieme al conteggio di tali argomenti, in modo simile ai valori di argv e di argc di runtime standard di C.

    Un esempio di chiamare questa API da C # e decomprimere l’array di stringhe risultante nel codice gestito può essere trovato in ” Conversione di stringa da riga di comando in Args [] usando l’API CommandLineToArgvW () .” Di seguito è riportata una versione leggermente più semplice dello stesso codice:

     [DllImport("shell32.dll", SetLastError = true)] static extern IntPtr CommandLineToArgvW( [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, out int pNumArgs); public static string[] CommandLineToArgs(string commandLine) { int argc; var argv = CommandLineToArgvW(commandLine, out argc); if (argv == IntPtr.Zero) throw new System.ComponentModel.Win32Exception(); try { var args = new string[argc]; for (var i = 0; i < args.Length; i++) { var p = Marshal.ReadIntPtr(argv, i * IntPtr.Size); args[i] = Marshal.PtrToStringUni(p); } return args; } finally { Marshal.FreeHGlobal(argv); } } 

    Mi dà fastidio che non ci sia alcuna funzione per dividere una stringa in base a una funzione che esamina ogni carattere. Se ci fosse, potresti scrivere così:

      public static IEnumerable SplitCommandLine(string commandLine) { bool inQuotes = false; return commandLine.Split(c => { if (c == '\"') inQuotes = !inQuotes; return !inQuotes && c == ' '; }) .Select(arg => arg.Trim().TrimMatchingQuotes('\"')) .Where(arg => !string.IsNullOrEmpty(arg)); } 

    Pur avendo scritto ciò, perché non scrivere i metodi di estensione necessari. Ok, mi hai parlato di questo …

    Innanzitutto, la mia versione di Split che accetta una funzione che deve decidere se il carattere specificato deve dividere la stringa:

      public static IEnumerable Split(this string str, Func controller) { int nextPiece = 0; for (int c = 0; c < str.Length; c++) { if (controller(str[c])) { yield return str.Substring(nextPiece, c - nextPiece); nextPiece = c + 1; } } yield return str.Substring(nextPiece); } 

    Potrebbe produrre alcune stringhe vuote a seconda della situazione, ma forse queste informazioni saranno utili in altri casi, quindi non rimuoverò le voci vuote in questa funzione.

    In secondo luogo (e più mondialmente) un piccolo aiutante che taglierà un paio di virgolette corrispondenti dall'inizio e alla fine di una stringa. È più esigente del metodo Trim standard: tratterà solo un carattere per ciascuna estremità e non taglierà da una sola estremità:

      public static string TrimMatchingQuotes(this string input, char quote) { if ((input.Length >= 2) && (input[0] == quote) && (input[input.Length - 1] == quote)) return input.Substring(1, input.Length - 2); return input; } 

    E suppongo che anche tu voglia dei test. Bene, va bene allora. Ma questa deve essere assolutamente l'ultima cosa! Innanzitutto una funzione di supporto che confronta il risultato della divisione con i contenuti dell'array previsti:

      public static void Test(string cmdLine, params string[] args) { string[] split = SplitCommandLine(cmdLine).ToArray(); Debug.Assert(split.Length == args.Length); for (int n = 0; n < split.Length; n++) Debug.Assert(split[n] == args[n]); } 

    Quindi posso scrivere test come questo:

      Test(""); Test("a", "a"); Test(" abc ", "abc"); Test("ab ", "a", "b"); Test("ab \"cd\"", "a", "b", "cd"); 

    Ecco il test per le tue esigenze:

      Test(@"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""[email protected]"" tasks:""SomeTask,Some Other Task"" -someParam", @"/src:""C:\tmp\Some Folder\Sub Folder""", @"/users:""[email protected]""", @"tasks:""SomeTask,Some Other Task""", @"-someParam"); 

    Si noti che l'implementazione ha la caratteristica in più che rimuoverà le virgolette attorno ad un argomento se questo ha senso (grazie alla funzione TrimMatchingQuotes). Credo che faccia parte della normale interpretazione da linea di comando.

    L’analizzatore della riga di comando di Windows si comporta come dici tu, diviso sullo spazio a meno che non ci sia una citazione non chiusa prima di essa. Consiglierei di scrivere il parser da solo. Qualcosa di simile forse:

      static string[] ParseArguments(string commandLine) { char[] parmChars = commandLine.ToCharArray(); bool inQuote = false; for (int index = 0; index < parmChars.Length; index++) { if (parmChars[index] == '"') inQuote = !inQuote; if (!inQuote && parmChars[index] == ' ') parmChars[index] = '\n'; } return (new string(parmChars)).Split('\n'); } 

    Ho preso la risposta da Jeffrey L Whitledge e l’ho migliorata un po ‘. Non ho ancora abbastanza crediti per commentare la sua risposta.

    Ora supporta sia le virgolette singole che doppie. È ansible utilizzare le virgolette nei parametri stessi utilizzando altre virgolette tipizzate.

    Strisce anche le virgolette dagli argomenti poiché questi non contribuiscono all’informazione dell’argomento.

      public static string[] SplitArguments(string commandLine) { var parmChars = commandLine.ToCharArray(); var inSingleQuote = false; var inDoubleQuote = false; for (var index = 0; index < parmChars.Length; index++) { if (parmChars[index] == '"' && !inSingleQuote) { inDoubleQuote = !inDoubleQuote; parmChars[index] = '\n'; } if (parmChars[index] == '\'' && !inDoubleQuote) { inSingleQuote = !inSingleQuote; parmChars[index] = '\n'; } if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ') parmChars[index] = '\n'; } return (new string(parmChars)).Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); } 

    Environment.GetCommandLineArgs ()

    La buona e pura soluzione gestita da Earwicker non è riuscita a gestire argomenti come questo:

     Test("\"He whispered to her \\\"I love you\\\".\"", "He whispered to her \"I love you\"."); 

    Ha restituito 3 elementi:

     "He whispered to her \"I love you\"." 

    Quindi ecco una soluzione per supportare il “quoted \” escape \ “quote”:

     public static IEnumerable SplitCommandLine(string commandLine) { bool inQuotes = false; bool isEscaping = false; return commandLine.Split(c => { if (c == '\\' && !isEscaping) { isEscaping = true; return false; } if (c == '\"' && !isEscaping) inQuotes = !inQuotes; isEscaping = false; return !inQuotes && Char.IsWhiteSpace(c)/*c == ' '*/; }) .Select(arg => arg.Trim().TrimMatchingQuotes('\"').Replace("\\\"", "\"")) .Where(arg => !string.IsNullOrEmpty(arg)); } 

    Testato con 2 casi aggiuntivi:

     Test("\"C:\\Program Files\"", "C:\\Program Files"); Test("\"He whispered to her \\\"I love you\\\".\"", "He whispered to her \"I love you\"."); 

    Inoltre, ha rilevato che anche la risposta accettata da Atif Aziz che utilizza CommandLineToArgvW non è riuscita. Ha restituito 4 elementi:

     He whispered to her \ I love you". 

    Spero che questo aiuti qualcuno in cerca di una tale soluzione in futuro.

    Google dice: C # /. NET Argomenti della riga di comando Parser

    Mi piacciono gli iteratori e al giorno d’oggi Linq rende IEnumerable facilmente utilizzabile come array di stringhe, quindi la mia opinione che segue lo spirito di Jeffrey L Whitledge è la risposta (come metodo di estensione alla stringa):

      public static IEnumerable ParseArguments(this string commandLine) { if (string.IsNullOrWhiteSpace(commandLine)) yield break; var sb = new StringBuilder(); bool inQuote = false; foreach (char c in commandLine) { if (c == '"' && !inQuote) { inQuote = true; continue; } if (c != '"' && !(char.IsWhiteSpace(c) && !inQuote)) { sb.Append(c); continue; } if (sb.Length > 0) { var result = sb.ToString(); sb.Clear(); inQuote = false; yield return result; } } if (sb.Length > 0) yield return sb.ToString(); } 

    Questo articolo di progetto sul codice è quello che ho usato in passato, è un bel po ‘di codice, ma potrebbe funzionare.

    Questo articolo di msdn è l’unica cosa che ho trovato che spiega come C # analizza gli argomenti della riga di comando.

    Spero possa aiutare!

    Nella tua domanda hai chiesto una regex, e io sono un grande fan e utente di loro, quindi quando ho avuto bisogno di fare lo stesso argomento diviso come te, ho scritto la mia regex dopo aver cercato su google e non trovando una soluzione semplice. Mi piacciono le soluzioni brevi, quindi ne ho fatto uno ed eccolo qui:

      var re = @"\G(""((""""|[^""])+)""|(\S+)) *"; var ms = Regex.Matches(CmdLine, re); var list = ms.Cast() .Select(m => Regex.Replace( m.Groups[2].Success ? m.Groups[2].Value : m.Groups[4].Value, @"""""", @"""")).ToArray(); 

    Gestisce spazi vuoti e virgolette tra virgolette e converte “” in “” incluso. Sentiti libero di usare il codice!

    So che questo è vecchio, ma qualcuno potrebbe trovare utile una soluzione puramente gestita . Ci sono troppi commenti “problema” per la funzione WINAPI e non sono disponibili su altre piattaforms. Ecco il mio codice che ha un comportamento ben definito (che puoi cambiare se vuoi). Dovrebbe fare lo stesso di quello che fanno .NET / Windows quando fornisce quel parametro string[] args , l’ho confrontato con un numero di valori “interessanti”.

    Questa è una classica implementazione della macchina di stato che prende ogni singolo carattere dalla stringa di input e lo interpreta per lo stato corrente, producendo output e un nuovo stato. Lo stato è definito nelle variabili escape , inQuote , hadQuote e prevCh , l’output è raccolto in currentArg e args .

    Alcune delle specialità che ho scoperto con esperimenti su un vero prompt dei comandi (Windows 7): \\ produce \ , \" produce " , "" all’interno di un intervallo tra virgolette produce " .

    Anche il personaggio ^ sembra magico: scompare sempre quando non lo raddoppia. Altrimenti non ha alcun effetto su una vera linea di comando. La mia implementazione non supporta questo, in quanto non ho trovato uno schema in questo comportamento. Forse qualcuno ne sa di più.

    Qualcosa che non si adatta a questo modello è il seguente comando:

     cmd /c "argdump.exe "abc"" 

    Il comando cmd sembra catturare le virgolette esterne e prendere il resto alla lettera. Ci deve essere qualche salsa magica speciale in questo.

    Non ho fatto benchmark sul mio metodo, ma lo considero abbastanza veloce. Non usa Regex e non esegue alcuna concatenazione di stringhe, ma utilizza un StringBuilder per raccogliere i caratteri per un argomento e inserirli in un elenco.

     ///  /// Reads command line arguments from a single string. ///  /// The string that contains the entire command line. /// An array of the parsed arguments. public string[] ReadArgs(string argsString) { // Collects the split argument strings List args = new List(); // Builds the current argument var currentArg = new StringBuilder(); // Indicates whether the last character was a backslash escape character bool escape = false; // Indicates whether we're in a quoted range bool inQuote = false; // Indicates whether there were quotes in the current arguments bool hadQuote = false; // Remembers the previous character char prevCh = '\0'; // Iterate all characters from the input string for (int i = 0; i < argsString.Length; i++) { char ch = argsString[i]; if (ch == '\\' && !escape) { // Beginning of a backslash-escape sequence escape = true; } else if (ch == '\\' && escape) { // Double backslash, keep one currentArg.Append(ch); escape = false; } else if (ch == '"' && !escape) { // Toggle quoted range inQuote = !inQuote; hadQuote = true; if (inQuote && prevCh == '"') { // Doubled quote within a quoted range is like escaping currentArg.Append(ch); } } else if (ch == '"' && escape) { // Backslash-escaped quote, keep it currentArg.Append(ch); escape = false; } else if (char.IsWhiteSpace(ch) && !inQuote) { if (escape) { // Add pending escape char currentArg.Append('\\'); escape = false; } // Accept empty arguments only if they are quoted if (currentArg.Length > 0 || hadQuote) { args.Add(currentArg.ToString()); } // Reset for next argument currentArg.Clear(); hadQuote = false; } else { if (escape) { // Add pending escape char currentArg.Append('\\'); escape = false; } // Copy character from input, no special meaning currentArg.Append(ch); } prevCh = ch; } // Save last argument if (currentArg.Length > 0 || hadQuote) { args.Add(currentArg.ToString()); } return args.ToArray(); } 

    Attualmente, questo è il codice che ho:

      private String[] SplitCommandLineArgument(String argumentString) { StringBuilder translatedArguments = new StringBuilder(argumentString); bool escaped = false; for (int i = 0; i < translatedArguments.Length; i++) { if (translatedArguments[i] == '"') { escaped = !escaped; } if (translatedArguments[i] == ' ' && !escaped) { translatedArguments[i] = '\n'; } } string[] toReturn = translatedArguments.ToString().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); for(int i = 0; i < toReturn.Length; i++) { toReturn[i] = RemoveMatchingQuotes(toReturn[i]); } return toReturn; } public static string RemoveMatchingQuotes(string stringToTrim) { int firstQuoteIndex = stringToTrim.IndexOf('"'); int lastQuoteIndex = stringToTrim.LastIndexOf('"'); while (firstQuoteIndex != lastQuoteIndex) { stringToTrim = stringToTrim.Remove(firstQuoteIndex, 1); stringToTrim = stringToTrim.Remove(lastQuoteIndex - 1, 1); //-1 because we've shifted the indicies left by one firstQuoteIndex = stringToTrim.IndexOf('"'); lastQuoteIndex = stringToTrim.LastIndexOf('"'); } return stringToTrim; } 

    Non funziona con le virgolette di escape, ma funziona per i casi che ho incontrato finora.

    Questa è una risposta al codice di Anton, che non funziona con le virgolette di escape. Ho modificato 3 posizioni.

    1. Il costruttore di StringBuilder in SplitCommandLineArguments , che sostituisce qualsiasi \ “ con \ r
    2. Nel ciclo for in SplitCommandLineArguments , ora reinserisco il carattere \ r in \ “ .
    3. Modificato il metodo SplitCommandLineArgument da statico privato a pubblico .

     public static string[] SplitCommandLineArgument( String argumentString ) { StringBuilder translatedArguments = new StringBuilder( argumentString ).Replace( "\\\"", "\r" ); bool InsideQuote = false; for ( int i = 0; i < translatedArguments.Length; i++ ) { if ( translatedArguments[i] == '"' ) { InsideQuote = !InsideQuote; } if ( translatedArguments[i] == ' ' && !InsideQuote ) { translatedArguments[i] = '\n'; } } string[] toReturn = translatedArguments.ToString().Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries ); for ( int i = 0; i < toReturn.Length; i++ ) { toReturn[i] = RemoveMatchingQuotes( toReturn[i] ); toReturn[i] = toReturn[i].Replace( "\r", "\"" ); } return toReturn; } public static string RemoveMatchingQuotes( string stringToTrim ) { int firstQuoteIndex = stringToTrim.IndexOf( '"' ); int lastQuoteIndex = stringToTrim.LastIndexOf( '"' ); while ( firstQuoteIndex != lastQuoteIndex ) { stringToTrim = stringToTrim.Remove( firstQuoteIndex, 1 ); stringToTrim = stringToTrim.Remove( lastQuoteIndex - 1, 1 ); //-1 because we've shifted the indicies left by one firstQuoteIndex = stringToTrim.IndexOf( '"' ); lastQuoteIndex = stringToTrim.LastIndexOf( '"' ); } return stringToTrim; } 

    puoi dare un’occhiata al codice che ho postato ieri:

    http://social.msdn.microsoft.com/Forums/fr-FR/netfx64bit/thread/2dfe45f5-7940-48cd-bd57-add8f3d94102

    Divide un nome file + argomenti nella stringa []. Percorso breve, variabile environnement, l’estensione del file mancante viene gestita.

    (Inizialmente era per UninstallString nel registro).

     public static string[] SplitArguments(string args) { char[] parmChars = args.ToCharArray(); bool inSingleQuote = false; bool inDoubleQuote = false; bool escaped = false; bool lastSplitted = false; bool justSplitted = false; bool lastQuoted = false; bool justQuoted = false; int i, j; for(i=0, j=0; i 

    basato sulla risposta di Vapor in the Alley , anche questo supporta ^ escape

    Esempi:

    • questa è una prova
      • Questo
      • è
      • un
      • test
    • questa è una prova
      • Questo
      • è un
      • test
    • questo ^ "è un test ^"
      • Questo
      • un"
      • test
    • questo "" "è un test ^^"
      • Questo
      • è un ^ test

    supporta anche più spazi (interrompe gli argomenti solo una volta per blocco di spazi)

    Prova questo codice:

      string[] str_para_linha_comando(string str, out int argumentos) { string[] linhaComando = new string[32]; bool entre_aspas = false; int posicao_ponteiro = 0; int argc = 0; int inicio = 0; int fim = 0; string sub; for(int i = 0; i < str.Length;) { if (entre_aspas) { // está entre aspas sub = str.Substring(inicio+1, fim - (inicio+1)); linhaComando[argc - 1] = sub; posicao_ponteiro += ((fim - posicao_ponteiro)+1); entre_aspas = false; i = posicao_ponteiro; } else { tratar_aspas: if (str.ElementAt(i) == '\"') { inicio = i; fim = str.IndexOf('\"', inicio + 1); entre_aspas = true; argc++; } else { // se não for aspas, então ler até achar o primeiro espaço em branco if (str.ElementAt(i) == ' ') { if (str.ElementAt(i + 1) == '\"') { i++; goto tratar_aspas; } // pular os espaços em branco adiconais while(str.ElementAt(i) == ' ') i++; argc++; inicio = i; fim = str.IndexOf(' ', inicio); if (fim == -1) fim = str.Length; sub = str.Substring(inicio, fim - inicio); linhaComando[argc - 1] = sub; posicao_ponteiro += (fim - posicao_ponteiro); i = posicao_ponteiro; if (posicao_ponteiro == str.Length) break; } else { argc++; inicio = i; fim = str.IndexOf(' ', inicio); if (fim == -1) fim = str.Length; sub = str.Substring(inicio, fim - inicio); linhaComando[argc - 1] = sub; posicao_ponteiro += fim - posicao_ponteiro; i = posicao_ponteiro; if (posicao_ponteiro == str.Length) break; } } } } argumentos = argc; return linhaComando; } 

    È scritto in portoghese.

    Ecco una fodera che fa il lavoro (vedi la linea che fa tutto il lavoro all’interno del metodo BurstCmdLineArgs (…)). Non è quella che definirei la riga di codice più leggibile, ma puoi scomporla per motivi di leggibilità. È semplice di proposito e non funziona bene per tutti i casi di argomenti (come gli argomenti dei nomi di file che contengono il delimitatore di caratteri a stringa divisa in essi). Questa soluzione ha funzionato bene nelle mie soluzioni che lo utilizzano. Come ho detto, il lavoro viene svolto senza un codice di codice per gestire tutti i possibili argomenti in formato n-fattoriale.

     using System; using System.Collections.Generic; using System.Linq; namespace CmdArgProcessor { class Program { static void Main(string[] args) { // test switches and switches with values // -test1 1 -test2 2 -test3 -test4 -test5 5 string dummyString = string.Empty; var argDict = BurstCmdLineArgs(args); Console.WriteLine("Value for switch = -test1: {0}", argDict["test1"]); Console.WriteLine("Value for switch = -test2: {0}", argDict["test2"]); Console.WriteLine("Switch -test3 is present? {0}", argDict.TryGetValue("test3", out dummyString)); Console.WriteLine("Switch -test4 is present? {0}", argDict.TryGetValue("test4", out dummyString)); Console.WriteLine("Value for switch = -test5: {0}", argDict["test5"]); // Console output: // // Value for switch = -test1: 1 // Value for switch = -test2: 2 // Switch -test3 is present? True // Switch -test4 is present? True // Value for switch = -test5: 5 } public static Dictionary BurstCmdLineArgs(string[] args) { var argDict = new Dictionary(); // Flatten the args in to a single string separated by a space. // Then split the args on the dash delimiter of a cmd line "switch". // Eg -mySwitch myValue // or -JustMySwitch (no value) // where: all values must follow a switch. // Then loop through each string returned by the split operation. // If the string can be split again by a space character, // then the second string is a value to be paired with a switch, // otherwise, only the switch is added as a key with an empty string as the value. // Use dictionary indexer to retrieve values for cmd line switches. // Use Dictionary::ContainsKey(...) where only a switch is recorded as the key. string.Join(" ", args).Split('-').ToList().ForEach(s => argDict.Add(s.Split()[0], (s.Split().Count() > 1 ? s.Split()[1] : ""))); return argDict; } } } 

    Non penso ci siano citazioni singole o virgolette per applicazioni C #. La seguente funzione sta funzionando bene per me:

     public static IEnumerable SplitArguments(string commandLine) { Char quoteChar = '"'; Char escapeChar = '\\'; Boolean insideQuote = false; Boolean insideEscape = false; StringBuilder currentArg = new StringBuilder(); // needed to keep "" as argument but drop whitespaces between arguments Int32 currentArgCharCount = 0; for (Int32 i = 0; i < commandLine.Length; i++) { Char c = commandLine[i]; if (c == quoteChar) { currentArgCharCount++; if (insideEscape) { currentArg.Append(c); // found \" -> add " to arg insideEscape = false; } else if (insideQuote) { insideQuote = false; // quote ended } else { insideQuote = true; // quote started } } else if (c == escapeChar) { currentArgCharCount++; if (insideEscape) // found \\ -> add \\ (only \" will be ") currentArg.Append(escapeChar + escapeChar); insideEscape = !insideEscape; } else if (Char.IsWhiteSpace(c)) { if (insideQuote) { currentArgCharCount++; currentArg.Append(c); // append whitespace inside quote } else { if (currentArgCharCount > 0) yield return currentArg.ToString(); currentArgCharCount = 0; currentArg.Clear(); } } else { currentArgCharCount++; if (insideEscape) { // found non-escaping backslash -> add \ (only \" will be ") currentArg.Append(escapeChar); currentArgCharCount = 0; insideEscape = false; } currentArg.Append(c); } } if (currentArgCharCount > 0) yield return currentArg.ToString(); } 

    Non sono sicuro se ti ho capito, ma il problema è che il carattere usato come splitter si trova anche nel testo? (Tranne che è sfuggito con doppio “?)

    In tal caso, creerei un ciclo for e sostituiremo tutte le istanze in cui <"> è presente con <|> (o un altro carattere” sicuro “, ma assicurati che sostituisca solo <">, e non <">>

    Dopo aver iterato la stringa, avrei fatto come precedentemente pubblicato, diviso la stringa, ma ora sul carattere <|>

    EDIT: Per la leggibilità, ho aggiunto, vale a dire “è scritto come <">, dal momento che è diventato un po ‘poco chiaro cosa intendevo quando ho scritto solo “” e “, o |

    Sì, l’object stringa ha una funzione incorporata chiamata Split () che accetta un singolo parametro che specifica il carattere da cercare come delimitatore e restituisce una serie di stringhe (stringa []) con i singoli valori in essa contenuti