C # Rimozione di caratteri separatori dalle stringhe tra virgolette

Sto scrivendo un programma che deve rimuovere i caratteri separatori dalle stringhe tra virgolette nei file di testo.

Per esempio:

"Hello, my name is world" 

Deve essere:

 "Hello my name is world" 

All’inizio sembra abbastanza facile (pensavo che sarebbe), ma è necessario rilevare quando inizia la citazione, quando termina la citazione, quindi cercare quella stringa specifica per i caratteri separatori. Come?

Ho sperimentato con alcuni Regex ma continuo a sentirmi confuso!

Qualche idea? Anche solo per far rotolare la palla, sono solo perplesso.

 string pattern = "\"([^\"]+)\""; value = Regex.Match(textToSearch, pattern).Value; string[] removalCharacters = {",",";"}; //or any other characters foreach (string character in removalCharacters) { value = value.Replace(character, ""); } 

perché non provare a farlo con Linq?

 var x = @" this is a great whatever ""Hello, my name is world"" and all that"; var result = string.Join(@"""", x.Split('"'). Select((val, index) => index%2 == 1 ? val.Replace(",", "") : val).ToArray()); 

Usando un modello regex con un look-ahead il pattern sarebbe: "\"(?=[^\"]+,)[^\"]+\""

\" Corrisponde alla doppia virgoletta di apertura. Il look-ahead (?=[^\"]+,) Tenterà di far corrispondere una virgola all’interno del testo quotato. Quindi abbiniamo il resto della stringa finché non è una doppia virgola [^\"]+ , quindi corrispondiamo alla doppia virgola di chiusura \" .

L’utilizzo di Regex.Replace consente un approccio compatto per modificare il risultato e rimuovere le virgole indesiderate.

 string input = "\"Hello, my name, is world\""; string pattern = "\"(?=[^\"]+,)[^\"]+\""; string result = Regex.Replace(input, pattern, m => m.Value.Replace(",", "")); Console.WriteLine(result); 

Quello che vuoi scrivere è chiamato “lexer” (o in alternativa un “tokenizer”), che legge il carattere di input per carattere e lo suddivide in token. Questo è generalmente il modo in cui l’analisi in un compilatore funziona (come primo passo). Un lexer interromperà il testo in un stream di token (letterale stringa, identificatore, “(“, ecc.) Il parser prende quindi quei token e li usa per produrre un albero di analisi.

Nel tuo caso, hai solo bisogno di un lexer. Avrai 2 tipi di token “stringhe tra virgolette” e “tutto il resto”.

Devi solo scrivere codice per suddividere l’input in token. Per impostazione predefinita, qualcosa è un token “tutto il resto”. Un token di stringa inizia quando vedi un “, e termina quando vedi il prossimo”. Se stai leggendo il codice sorgente potresti avere a che fare con cose come \ “o” “come casi speciali.

Una volta che hai fatto ciò, puoi semplicemente scorrere i token e fare ciò che è necessario per elaborare i token “stringa”.

Ho dovuto fare qualcosa di simile in un’applicazione che uso per tradurre file flat. Questo è l’approccio che ho preso: (solo una copia / incolla dalla mia applicazione)

  protected virtual string[] delimitCVSBuffer(string inputBuffer) { List output = new List(); bool insideQuotes = false; StringBuilder fieldBuffer = new StringBuilder(); foreach (char c in inputBuffer) { if (c == FieldDelimiter && !insideQuotes) { output.Add(fieldBuffer.Remove(0, 1).Remove(fieldBuffer.Length - 1, 1).ToString().Trim()); fieldBuffer.Clear(); continue; } else if (c == '\"') insideQuotes = !insideQuotes; fieldBuffer.Append(c); } output.Add(fieldBuffer.Remove(0, 1).Remove(fieldBuffer.Length - 1, 1).ToString().Trim()); return output.ToArray(); } 

Quindi immagino che tu abbia un lungo testo con un sacco di citazioni all’interno? Vorrei fare un metodo che faccia qualcosa del genere:

  1. Corri pensato allo spago finché non incontri il primo ”
  2. Quindi prendi la sottostringa fino alla successiva “, e fai una str.Replace (“, “,” “) e sostituisci anche qualsiasi altro carattere che vuoi sostituire.
  3. Quindi vai senza sostituire finché non incontri il prossimo “e continua fino alla fine.

MODIFICARE

Ho appena avuto un’idea migliore. Che dire di questo:

  string mycompletestring = "This is a string\"containing, a quote\"and some more text"; string[] splitstring = mycompletestring.Split('"'); for (int i = 1; i < splitstring.Length; i += 2) { splitstring[i] = splitstring[i].Replace(",", ""); } StringBuilder builder = new StringBuilder(); foreach (string s in splitstring) { builder.Append(s + '"'); } mycompletestring = builder.ToString().Substring(0, builder.ToString().Length - 1); 

Penso che ci dovrebbe essere un modo migliore di combinare la stringa in una con un "tra di loro alla fine, ma non ne conosco di migliori, quindi sentiti libero di suggerirti un buon metodo qui 🙂

Ok, questo è un po ‘strano, ma funziona.

Quindi prima di tutto dividi la tua stringa in parti, in base al " personaggio:

 string msg = "this string should have a comma here,\"but, there should be no comma in this bit\", and there should be a comma back at that and"; var parts = msg.Split('"'); 

quindi è necessario unire la stringa di nuovo insieme sul " carattere, dopo aver rimosso ogni virgola in ogni altra parte:

 string result = string.Join("\"", RemoveCommaFromEveryOther(parts)); 

La funzione di rimozione appare così:

 IEnumerable RemoveCommaFromEveryOther(IEnumerable parts) { using (var partenum = parts.GetEnumerator()) { bool replace = false; while (partenum.MoveNext()) { if(replace) { yield return partenum.Current.Replace(",",""); replace = false; } else { yield return partenum.Current; replace = true; } } } } 

Il does richiede che includiate una direttiva using per System.Collections.Generic .

Ci sono molti modi per farlo: Lok alle funzioni string.Split() e string.IndexOfAny()

È ansible utilizzare string.Split (new char [] {‘,’, ”}, StringSplitOption.RemoveEmptyEntries) per inserire la frase in parole, quindi utilizzare la class StringBuilder per mettere insieme le parole.

Calling string.Replace("[char to remove goes here]"',"") più volte con ogni carattere che vuoi rimuovere funzionerà anche.

MODIFICARE:

Chiama string.Split(new char[] {'\"'}, StringSplitOption.RemoveEmptyEntries) per ottenere un array di stringhe tra virgolette (“), quindi chiama Replace su ognuna di esse, quindi metti le stringhe insieme a StringBuilder .