2010-03-26 10 views
7

Potrzebuję 2 zasady "zamień" - moje zasady to, zamień wszystkie otwarte pareny "(" z łącznikiem "-" i usuń wszystkie zamykające parens ")".ciąg "wyszukaj i zamień" używając .NET regex

Tak na przykład w ten sposób:

"foobar (baz2)" staną

"foobar-baz2"

Obecnie zrobić to w ten sposób - ale moje przeczucie regex byłoby czystsze .

myString.Replace("(", "-").Replace(")", ""); 
+0

Wszystko - bardzo dziękuję - bardzo szczęśliwy, moje początkowe instynkty były poprawne. – rsturim

Odpowiedz

7

nie pojadę do RegEx do tego - co robisz jest po prostu w porządku. Jest to jasne i proste ... Wyrażenia regularne raczej nie sprawią, że stanie się to prostsze lub jaśniejsze. Będziesz nadal musiał wykonać dwa połączenia z numerem Replace, ponieważ twoje zastępstwa są różne dla każdego przypadku.

+0

Problem nie zasługuje na przejście do Regexa ... Niech to będzie proste ... – LorenVS

+0

Wystarczy jedno połączenie (patrz mój przykład). Niemniej jednak regularna wymiana jest najlepsza w tym przypadku. –

1

Nie. To jest idealnie czyste.

W takim razie trzeba by mieć dwa wyrażenia regularne, ponieważ zmienne zastępcze są różne.

+0

Technicznie w .NET możesz określić delegata, który oceni łańcuch zastępczy, ale teraz po prostu stajemy się bardziej nieczyste. – LorenVS

+0

Wystarczy jedno wyrażenie regularne. –

+0

Technicznie, tak. Ale jak już zauważył LorenVS, po prostu sprawia, że ​​całe wyrażenie jest mniej jasne. – Thomas

1

Powiedziałbym, że używaj tego, co masz - jest bardziej łatwy do odczytania/konserwacji. Regeksy są bardzo potężne, ale czasami bardzo mylące. Dla czegoś tak prostego, powiedziałbym, nie używaj nawet Regeksów.

3

Jamie Zawinski nagle przychodzi mi do głowy: „Wiem, użyję wyrażeń regularnych”

Niektórzy ludzie, w konfrontacji z problemem, pomyśl Teraz mają dwa problemy.

Uważam też, że LBuszkin ma rację w tym przypadku. Twoje rozwiązanie działa i jest czytelne.

1

Myślę, że regex będzie trochę kruchy dla tego rodzaju rzeczy. Jeśli wersja .NET ma metody rozszerzenie i chcesz czystsze składni, która skaluje można wprowadzić metodę rozszerzenia takiego:

public static class StringExtensions 
{ 
    public static string ReplaceMany(this string s, Dictionary<string, string> replacements) 
    { 
     var sb = new StringBuilder(s); 
     foreach (var replacement in replacements) 
     { 
      sb = sb.Replace(replacement.Key, replacement.Value); 
     } 
     return sb.ToString(); 
    } 
} 

Więc teraz budować swoją słownika zamienniki ...

var replacements = new Dictionary<string, string> { {"(", "-"}, {")", ""} }; 

I zadzwonić ReplaceMany:

var result = "foobar(baz2)".ReplaceMany(replacements); // result = foobar-baz2 

Jeśli naprawdę chcesz, aby pokazać swoje intencje można aliasu Dictionary<string,string> do StringReplacements:

//At the top 
using StringReplacements = System.Collections.Generic.Dictionary<string,string>; 

//In your function 
var replacements = new StringReplacements() { {"(", "-"}, {")", ""} }; 
var result = "foobar(baz2)".ReplaceMany(replacements); 

Może być przesadą tylko dwa zamienniki, ale jeśli masz wiele, aby go będzie czystsze niż .Replace().Replace().Replace().Replace()....

2

Możesz użyć jednego wyrażenia regularnego, aby zastąpić oba wystąpienia w jednym wierszu, ale byłoby to mniej "wyrozumiałe" niż dwa pojedyncze zamienniki ciągu reguł.

Przykład:

Kod, który będzie wykorzystywany do tego, co chcesz z regex byłoby:

Regex.Replace(myString, @"([^\(]*?)\(([^\)]*?)\)", "$1-$2"); 

to będzie działać dobrze dla przykładu, że dokładnie podany. Jeśli nastąpiła jakakolwiek zmiana miejsca i liczby znaków "(" i ")", regex ulegnie zerwaniu. Możesz wtedy poprawić to za pomocą większej ilości wyrażeń regularnych, ale stamtąd będzie po prostu coraz brzydsza i brzydsza.

Regex to niesamowity wybór dla aplikacji, które są bardziej sztywne.

0

Regex jest przesadny dla takiego prostego scenariusza. To, co masz, jest doskonałe. Chociaż Twoje pytanie zostało już odpowiedział, chciałem pisać, aby wykazać, że jeden wzór regex jest wystarczająca:

string input = "foobar(baz2)"; 
string pattern = "([()])"; 
string result = Regex.Replace(input, pattern, m => m.Value == "(" ? "-" : ""); 
Console.WriteLine(result); 

Chodzi o to, aby uchwycić nawiasów w grupie. Użyłem [()], która jest klasą postaci, która będzie pasować do tego, o co nam chodzi. Zauważ, że wewnątrz klasy postaci nie trzeba ich zbierać. Alternatywnie wzór mógł być @"(\(|\))", w którym to przypadku konieczne jest ucieczkę.

Następnie metoda Replace używa MatchEvaluator i sprawdzamy, czy zrobione wartość jest otwarcie ( czy nie. Jeśli tak, zwracana jest wartość -. Jeśli nie, to wiemy, na podstawie naszego ograniczonego wzoru, że musi to być zamykanie ) i zwracamy pusty ciąg znaków.

0

Oto zabawne rozwiązanie oparte na LINQ. To może nie być najlepszym rozwiązaniem, ale to interesująca anyways:

public string SearchAndReplace(string input) 
{ 
    var openParen = '('; 
    var closeParen = ')'; 
    var hyphen = '-'; 
    var newChars = input 
     .Where(c => c != closeParen) 
     .Select(c => c == openParen ? hyphen : c); 
    return new string(newChars.ToArray()); 
} 

2 ciekawe notatki na temat tej realizacji:

  • nie wymaga skomplikowanego wyrażenia regularnego, więc można uzyskać lepszą wydajność i łatwiejszą konserwacji .
  • W przeciwieństwie do string.Replace implementations, ta metoda przydziela dokładnie 1 ciąg znaków.

Nieźle!

Powiązane problemy