2010-11-18 22 views
4

Ayraç karakterlerini metin dosyalarındaki alıntı dizelerden kaldırması gereken bir program yazıyorum. ÖrneğinC# Ayırıcı karakterlerden ayraç karakterlerini kaldırma

:

"Hello, my name is world" 

olmak Has:

"Hello my name is world" 

Bu (Ben olacağını düşündüm) ilk başta oldukça kolay geliyor, ama sen, ne zaman alıntı başladığında algılamak gerekir Alıntı sona erer, ardından ayırıcı karakterler için belirli bir dizeyi arar. Nasıl?

Bazı Regex'leri denedim ama kendimi karıştırmaya devam ediyorum!

Herhangi bir fikrin var mı? Sadece topu yuvarlamak için bir şey, ben sadece tamamen güldüm. string.Split() ve string.IndexOfAny() String.split kullanabilirsiniz

(yeni char [] { ' '''}, StringSplitOption.RemoveEmptyEntries) slipt değiştiren fonksiyonları Lok:

+1

CSV için ayrıştırılabilir hale getirmek amacıyla virgülleri kaldırıyor musunuz? Öyleyse, "standart" CSV biçimini izleyen tokenleri çıkarmak için RegEx'ler kullanılabilir. Değilse, bu yorumu dikkate almayın. –

cevap

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

Regex'te noktayı kullanırken dikkatli olmalısınız; .Net'de açgözlüdür (yani ilk açık teklifte başlayacak ve son yakın teklifte sona erecektir). Bu nedenle, aradaki tüm virgülleri ve yarıları kaybedersiniz. Ancak, bunu yapabilirdiniz: 'string pattern =" \ "([^ \"] +) \ ""; açık alıntıda başlayacak ve başka bir teklif bulduğunda duracaktır. –

+0

Teşekkürler Örnek: Normal ifadeler için oldukça yeni oldum, bu yüzden bahşiş için teşekkürler. RegEx için – Matt

+0

+1 (iyi olduğu şey için kullanın) –

-1

Bunu yapmanın pek çok yolu vardır ifadeyi sözcüklere ekleyin, ardından kelimeleri bir araya getirmek için StringBuilder sınıfını kullanın.

string.Replace("[char to remove goes here]"',"") numaralı telefonu çağırmak istediğiniz her bir char ile birden çok kez çalışacaksınız.

DÜZENLEME:.

Çağrı string.Split(new char[] {'\"'}, StringSplitOption.RemoveEmptyEntries) sonra bunların her biri üzerinde Replace çağrı tırnak (") arasındadır dize dizisi elde sonra StringBuilder birlikte dizeleri koymak

+1

İpucu: string.Split (yeni char [] {'\ "'} dizesini string.Split ('"'} –

+0

olarak yazabilirsiniz. Düzenlemeniz, thestring.replace (") ile aynıdır. \ "," ")', diğer tüm dizgilerdeki virgülleri değiştirmeniz gerekir ve 'StringSplitOption.RemoveEmptyEntries', dizginiz bir alıntı ile başlar ve herhangi bir boş alıntı bloğunu kaybederse dizenin yanlış sırasını almanız anlamına gelir. Metin: -1 –

0

Yani seni tahmin içeride tırnak bir sürü bazı uzun metin var böyle bir şey yapan bir yöntem yapacak: öncelikle "karşılaşıncaya kadar

  1. Çalıştır dize düşünce
  2. Ardından, alt dizgiyi bir sonraki "ye kadar yapın ve bir str.Replace (", "," ") yapın ve değiştirmek istediğiniz diğer karakterleri de değiştirin.
  3. Sonra sıradaki karşılaşıncaya kadar değiştirmeden gitmek "ve sonuna kadar devam

DÜZENLEME Ben sadece daha iyi bir fikrim var

ne bu konuda.:.

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

Sanırım, dizgiyi "aralarında bir arada" ile birleştirmenin daha iyi bir yolu olmalı, ama daha iyi bir tanıdığım yok, bu yüzden burada iyi bir yöntem önermek için çekinmeyin :)

+0

Bu, yapmam gereken gibi geliyor.Aslında bir StreamReader kullanarak dosyalarda okuyorum, ancak ReadLine() kullanarak satır satır okuyorum. Bunu her satıra mı yapmalıyım? –

+0

Neden tüm dosyayı bir seferde okumuyorsunuz, benim yaklaşımımı gönderinin ** EDIT ** kısmının içinde kullan ve sonra tekrar dosyaya yaz. Alıntı bir satırda başlarsa ve başka bir satırda bitiyorsa (en azından benim uygulamamla, ancak elbette kendi uygulamanızı yaparsanız bunu da düzeltebilirsiniz), satır satır çizgisi yapmak berbat olur. –

+0

Bir teklifin birden fazla satıra denk gelmesi durumunda mutlaka her satıra bunu yapmak istemez. Tüm metni bir kerede almak için ReadToEnd'i kullanmak ve daha sonra önermek istediğiniz şeyi yapmak istersiniz. –

0

Düz dosyaları çevirmek için kullandığım bir uygulamada benzer bir şey yapmak zorunda kaldım.(Benim uygulamadan sadece kopyala/yapıştır) Ya bir "lexer" denir yazmak istiyorum

 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

Burada biraz daha fazla arka plan var. Bu girdiyi çevreleyen tırnaklar içeren bir grup virgülle ayrılmış dizgiler olabilir: Gibi "abc123", "123abc", "blah", ve tırnakların içindeki bir dizge dizisini döndürür. ihtiyacınız olan herhangi bir karakter değişimini yapabilirsiniz. "FieldDelimiter" belirttiğiniz herhangi bir karakter olabilir, ancak bu durumda bir virgül – Brosto

+0

Yapmak istediğiniz şey buysa, neden sadece string.plit ("" ') ve tüm dizeleri bile dizine eklediniz mi? –

+0

Yapılandırılabilir olması gerekiyordu, bu yüzden seçimimi sınırlandırabilirim. – Brosto

1

(veya alternatif bir "tokenizer") tarafından giriş karakterini okur: Bu Çektiğim yaklaşımdır karakter ve bunları tokenlere ayırır. Genelde bir derleyicide ayrıştırma nasıl çalışır (ilk adım olarak). Bir lexer metinleri bir simge dizisine (string literal, identifer, "(", etc) kırmayacaktır. Ayrıştırıcı bu simgeleri alır ve bunları bir ayrıştırma ağacı üretmek için kullanır.

Sizin durumunuzda, yalnızca Bir lexer'a ihtiyacınız var.İki tip "belirti dizgisi" ve "diğer her şey" olacaktır.

Girdiyi jetonlara bölmek için kod yazmanız yeterlidir. Varsayılan olarak bir şey "her şey" dir. Bir dize belirteci, bir "gördüğün ve bir sonraki gördüğünüzde bittiğinde" başladığında başlar. Eğer kaynak kodunu okursanız, özel durumlar gibi \ "veya" "gibi şeylerle uğraşmak zorunda kalabilirsiniz.

Bir kez Bunu yaptık, sonra sadece jetonların üzerinde yineleyebilirsiniz d "string" token'larına ihtiyaç duyduğunuz her şeyi yapın.

2

Neden Linq ile denemeyin?

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 Benzer bir fikirle geldim, ancak linq kullanmıyorum –

0

Tamam, bu biraz tuhaf ama işe yarıyor.

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

o zaman her kesiminde her virgül çıkardıktan sonra, " karaktere tekrar bir araya dize katılması gerekir: Eğer " karaktere dayalı bölüme yukarı dize bölmek Yani ilk kapalı

:

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

kaldırma fonksiyonu şuna benzer:

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

Bu, System.Collections.Generic için bir kullanma yönergesi eklemenizi gerektirir. desen olurdu bir göz yeşil ışık ile regex deseni kullanarak

2

: "\"(?=[^\"]+,)[^\"]+\""

\" açılış maçları çift tırnak. İleriye dönük (?=[^\"]+,), alıntılanan metindeki bir virgülü eşleştirmeyi deneyecektir. Daha sonra çift tırnaklı [^\"]+ olmadığı sürece dizginin geri kalanıyla eşleşir, ardından kapanış çift tırnak işareti \" ile eşleşir. Regex.Replace kullanımı, sonucu değiştirmeye ve istenmeyen virgülleri kaldırmaya yönelik kompakt bir yaklaşım sağlar.

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