2010-11-18 14 views
4

Ich schreibe ein Programm, das Trennzeichen aus Strings in Anführungszeichen in Textdateien entfernen muss.C# Entfernen von Trennzeichen aus Strings in Anführungszeichen

Zum Beispiel:

"Hello, my name is world" 

Hat sein:

"Hello my name is world" 

Das klingt ganz einfach auf den ersten (ich dachte, es wäre), aber Sie müssen erkennen, wenn das Zitat beginnt, wenn Das Zitat endet, und suchen Sie dann diese spezifische Zeichenfolge nach Trennzeichen. Wie?

Ich habe mit einigen Regexs experimentiert, aber ich bekomme mich immer verwirrt!

Irgendwelche Ideen? Sogar nur etwas, um den Ball ins Rollen zu bringen, ich bin einfach völlig ratlos.

+1

Entfernen Sie die Kommas, um CSV parsen zu können? Wenn dies der Fall ist, stehen RegEx zur Verfügung, um die Token zu extrahieren, die dem CSV-Standardformat folgen. Wenn nicht, ignoriere diesen Kommentar. –

Antwort

3
string pattern = "\"([^\"]+)\""; 
value = Regex.Match(textToSearch, pattern).Value; 

string[] removalCharacters = {",",";"}; //or any other characters 
foreach (string character in removalCharacters) 
{ 
    value = value.Replace(character, ""); 
} 
+1

Sie müssen jedoch vorsichtig sein, wenn Sie den Punkt in Regex verwenden; in .Net ist es gierig (was bedeutet, dass es beim ersten offenen Zitat beginnt und beim letzten nahen Zitat endet). Daher würden Sie alle Kommas und Semis dazwischen verlieren. Sie könnten dies jedoch tun: 'string pattern =" \ "([^ \"] +) \ ""; 'beginnt bei offenem Zitat und stoppt, wenn es ein anderes Zitat findet. –

+0

Danke, ich werde das aktualisieren Beispiel: Ich bin ziemlich neu bei regulären Ausdrücken, danke für den Tipp – Matt

+0

+1 für RegEx (verwenden Sie es für das, was es gut ist) –

-1

Es gibt viele Möglichkeiten, dies zu tun: Lok an den Funktionen string.Split() und string.IndexOfAny()

Sie String.split verwenden können (new char [] { ' '''}, StringSplitOption.RemoveEmptyEntries) slipt die Phrase in Worte, dann verwenden Sie die StringBuilder Klasse, um die Wörter zusammen zu setzen.

Der Aufruf von string.Replace("[char to remove goes here]"',"") mehrmals mit jedem Zeichen, das Sie entfernen möchten, funktioniert auch.

EDIT:.

Anruf string.Split(new char[] {'\"'}, StringSplitOption.RemoveEmptyEntries) ein Array der Strings zu erhalten, die zwischen Anführungszeichen sind ("), dann Replace von ihnen auf jeden Anruf, legt dann die Saiten zusammen mit StringBuilder

+1

Hinweis: Sie können string.Split (new char [] {'\' '} als string.Split (' '' ' –

+0

Ihre Bearbeitung wird nicht funktionieren, da das ist das gleiche wie das Aufrufen von 'thestring.replace (" \ "," ")', müssen Sie die Kommas in jeder anderen Zeichenfolge ersetzen, und die 'StringSplitOption.RemoveEmptyEntries' bedeutet, dass Sie die falsche Reihenfolge für die Zeichenfolge erhalten, wenn Ihre Zeichenfolge mit einem Zitat beginnt und leere Angebotsblöcke aus verliert der Text. -1 –

0

Also ich denke, Sie haben einige langen Texte mit vielen Anführungszeichen innerhalb ich würde eine Methode machen, die so etwas wie dies funktioniert:

  1. Führen Sie die Zeichenfolge gedacht, bis Ihnen die ersten "
  2. begegnen
  3. Dann nehmen Sie den Teilstring bis zum nächsten ", und machen Sie eine str.Replace (", "," ") und ersetzen Sie auch alle anderen Zeichen, die Sie ersetzen möchten.
  4. geht dann ohne Austausch bis zum nächsten "begegnen und bis zum Ende fortsetzen

EDIT

Ich habe eine bessere Idee Was dazu:..

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); 

Ich denke, es sollte einen besseren Weg geben, die Saite mit einem "zwischen ihnen am Ende zu kombinieren, aber ich kenne keine besseren, also zögern Sie nicht, hier eine gute Methode vorzuschlagen :)

+0

Das klingt wie, was ich tun muss ..Ich lese tatsächlich Dateien mit einem StreamReader ein, aber ich lese zeilenweise mit ReadLine(). Soll ich das nur an jeder Zeile machen? –

+0

Warum nicht die gesamte Datei auf einmal lesen, meinen Ansatz innerhalb des ** EDIT ** -Teils des Beitrags verwenden und ihn dann auch wieder in die Datei schreiben? Zeilenweise zu tun wird durcheinander gebracht, wenn das Zitat auf einer Zeile beginnt und auf einer anderen Zeile endet (zumindest mit meiner Implementierung, aber natürlich können Sie das auch reparieren, wenn Sie möchten, dass Sie Ihre eigene Implementierung machen) –

+0

Sie würden nicht Ich möchte das nicht unbedingt für jede Zeile tun, falls ein Angebot mehr als eine Zeile umfasst. Sie sollten ReadToEnd verwenden, um den gesamten Text auf einmal zu erhalten, und dann tun, was vorgeschlagen wird. –

0

Ich musste etwas Ähnliches in einer Anwendung, die ich verwende, um flache Dateien zu übersetzen, tun.Dies ist der Ansatz, den ich nahm: (nur ein Copy/Paste aus meiner Anwendung)

 protected virtual string[] delimitCVSBuffer(string inputBuffer) { 
     List<string> output  = new List<string>(); 
     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(); 
    } 
+0

Ein wenig mehr Hintergrund hier. .. Die Eingabe dazu wäre eine Reihe von durch Kommata getrennten Strings mit Zitaten um sie herum, wie zum Beispiel: "abc123", "123abc", "blah" und es würde ein String-Array des Textes innerhalb der Anführungszeichen zurückgeben. Sie können alle erforderlichen Zeichenersetzungen vornehmen. Das Feld "FeldDelimiter" kann ein beliebiges Zeichen sein, aber in diesem Fall ist es ein Komma. – Brosto

+0

Wenn Sie das möchten, verwenden Sie einfach string.Split ('' '), und alle Saiten mit einem geraden Index zurückgeben? –

+0

Es soll konfigurierbar sein, damit ich das Trennzeichen meiner Wahl übergeben kann. – Brosto

1

Was möchten Sie ist eine „Lexer“ (oder alternativ eine „tokenizer“ genannt) zu schreiben, das liest das eingegebene Zeichen durch Zeichen und teilt es in Tokens auf. Im Allgemeinen funktioniert das Parsen in einem Compiler (als erster Schritt). Ein Lexer unterbricht Text in einen Strom von Token (String-Literal, Identifier, "(", usw.). Der Parser nimmt dann diese Token und verwendet sie, um einen Parse-Baum zu erzeugen.

In Ihrem Fall nur Sie brauche einen lexer Sie haben 2 Arten von Token "quoted strings", und "alles andere"

Sie müssen dann nur Code schreiben, um die Eingabe in Token zu brechen. Standardmäßig ist etwas ein "alles andere" token.Ein String-Token startet, wenn Sie ein ", und endet, wenn Sie die nächste" sehen. Wenn Sie Quellcode lesen, müssen Sie möglicherweise Dinge wie "oder" als Sonderfälle behandeln.

Sobald Sie Haben Sie das getan, dann können Sie einfach über die Token ein Iterieren d was immer Sie benötigen, auf den "String" -Token.

2

warum nicht versuchen, es mit Linq zu tun?

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()); 
+0

+1 Ich habe eine ähnliche Idee, aber nicht mit linq –

0

Ok, das ist ein bisschen verrückt, aber es funktioniert.

Also zunächst einmal Sie Ihren String in Teile aufgeteilt, basierend auf den " Charakter:

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('"'); 

dann müssen Sie die Zeichenfolge wieder zusammen auf dem " Charakter verbinden, nachdem jedes Komma in jedem anderen Teil zu entfernen :

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

Die Entfernungsfunktion sieht wie folgt aus:

IEnumerable<string> RemoveCommaFromEveryOther(IEnumerable<string> 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; 
      } 
     } 
    } 
} 

Das erfordert, dass Sie eine Verwendungsrichtlinie für System.Collections.Generic enthalten.

2

einen RegexMuster mit einem Vorgriff Mit dem Muster wäre: "\"(?=[^\"]+,)[^\"]+\""

Die \" entspricht die Öffnung doppelte Anführungszeichen. Die Vorausschau (?=[^\"]+,) wird versuchen, ein Komma innerhalb des zitierten Textes zu finden. Als nächstes stimmen wir den Rest der Zeichenkette ab, solange es kein Doppelzitat [^\"]+ ist, dann passen wir das schließende doppelte Zitat \" an.

Die Verwendung von Regex.Replace ermöglicht einen kompakten Ansatz zum Ändern des Ergebnisses und Entfernen der unerwünschten Kommas.

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