Parantezler (yuvarlak köşeli ayraçlar) arasında kalan metni nasıl ayıklayabilirim?


224

Bir dize var User name (sales)ve köşeli ayraçlar arasındaki metni ayıklamak istiyorum, bunu nasıl yaparım?

Alt dizeden şüpheliyim ama kapanış parantezine kadar okumayı öğrenemiyorum, metnin uzunluğu değişecektir.


2
Bize ne denediğini göster. Düzenli ifadeler kullanmaya baktınız mı?
George Stocker

Yanıtlar:


445

Düzenli ifadelerden uzak durmak isterseniz, aklıma gelen en basit yol:

string input = "User name (sales)";
string output = input.Split('(', ')')[1];

91
Dürüst olmak gerekirse, bu cevap olarak seçilmeliydi.
Pat Lindley

1
Split ("()" ile daha fazla daraltılmıyor mu? ToCharArray ()) [1]
prabhakaran

14
ve u birden fazla seçmek için aynı mantığı kullanmak istemeniz durumunda:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
dikkatli olun bu çözüm , vb salesiçeren giriş dizeleri ayıklamak)sales((sales(
Stefano Spinucci

435

Bunu yapmanın çok basit bir yolu düzenli ifadeler kullanmaktır:

Regex.Match("User name (sales)", @"\(([^)]*)\)").Groups[1].Value

(Çok komik) yoruma bir cevap olarak, burada bazı açıklamalarla aynı Regex:

\(             # Escaped parenthesis, means "starts with a '(' character"
    (          # Parentheses in a regex mean "put (capture) the stuff 
               #     in between into the Groups array" 
       [^)]    # Any character that is not a ')' character
       *       # Zero or more occurrences of the aforementioned "non ')' char"
    )          # Close the capturing group
\)             # "Ends with a ')' character"

504
İnsanlar "basit bir yol düzenli ifadeler kullanmaktır" dediğinde ve daha sonra çözülemez bir hiyeroglif dizisine ne kadar değer sunduğunu seviyorum (özellikle farklı insanlar regex önerdiğinde ve her biri aynı sorun için farklı bir hiyeroglif seti geldiğinde eğlenceli ). :)
Deltics

47
Yığında ne olup bittiğini açıklayan neredeyse yeterli cevap yok. Harika açıklama için teşekkürler .
Sandy Gifford

Başlangıçta '@' kullanıyorsanız, parantezden kaçmanız gerekmez mi?
sıra 1

10
@ rank1 parantezden kaçmanız gerekir. Burada @ teklifleri ters eğik çizgiler kaçmak gerek yok olmasıdır. Yani @ olmadan "\\ (([^)] *) \\)" gibi olur.
Diadistis

Bu yuvalanmış grupları iyi işlemez. Değiştirildivar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen

91

Yalnızca bir çift paranteziniz olduğunu varsayarsak.

string s = "User name (sales)";
int start = s.IndexOf("(") + 1;
int end = s.IndexOf(")", start);
string result = s.Substring(start, end - start);

7
(satış) yerine "satış" istiyorsanız alt dizede başlat + 1 daha doğru
Joze

1
ne olacak s = "Kullanıcı) adı (Satış)"?
dotnetstep

@dotnetstep haklı olmalısınız int end = s.IndexOf(")", start);. Bir düzenlemeyi sıraya
koydum

1
"(" .Length; +1'den daha iyi. Düzenleme gönderdi. Ayrıca bir işlev ekledi.
Ave

24

Bu işlevi kullanın:

public string GetSubstringByString(string a, string b, string c)
    {
        return c.Substring((c.IndexOf(a) + a.Length), (c.IndexOf(b) - c.IndexOf(a) - a.Length));
    }

ve işte kullanımı:

GetSubstringByString("(", ")", "User name (sales)")

ve çıktı:

sales

16

Düzenli ifadeler burada en iyi araç olabilir. Onlara aşina değilseniz, harika bir küçük regex aracı olan Expresso'yu yüklemenizi tavsiye ederim .

Gibi bir şey:

Regex regex = new Regex("\\((?<TextInsideBrackets>\\w+)\\)");
string incomingValue = "Username (sales)";
string insideBrackets = null;
Match match = regex.Match(incomingValue);
if(match.Success)
{
    insideBrackets = match.Groups["TextInsideBrackets"].Value;
}

14
string input = "User name (sales)";

string output = input.Substring(input.IndexOf('(') + 1, input.IndexOf(')') - input.IndexOf('(') - 1);

1
Tabii ki ilk braketin yerini sadece bir kez hesaplamalısınız.
Martin Brown

İç paranteziniz input = "User name (sales(1))varsa, örneğin iç parantez input.LastIndexOf(')')varsa ya da olmasa da işe yarayacak olanı kullanmak isteyebilirsiniz .
Ben

13

Belki normal bir ifade? Bunun işe yarayacağını düşünüyorum ...

\(([a-z]+?)\)

7
using System;
using System.Text.RegularExpressions;

private IEnumerable<string> GetSubStrings(string input, string start, string end)
{
    Regex r = new Regex(Regex.Escape(start) +`"(.*?)"`  + Regex.Escape(end));
    MatchCollection matches = r.Matches(input);
    foreach (Match match in matches)
    yield return match.Groups[1].Value;
}

4

Normal İfade Kullanın:

string test = "(test)"; 
string word = Regex.Match(test, @"\((\w+)\)").Groups[1].Value;
Console.WriteLine(word);

4
int start = input.IndexOf("(") + 1;
int length = input.IndexOf(")") - start;
output = input.Substring(start, length);

2
input.Remove(input.IndexOf(')')).Substring(input.IndexOf('(') + 1);

2

regexYöntem bence üstündür, ancak mütevazı kullanmak istiyorsasubstring

string input= "my name is (Jayne C)";
int start = input.IndexOf("(");
int stop = input.IndexOf(")");
string output = input.Substring(start+1, stop - start - 1);

veya

string input = "my name is (Jayne C)";
string output  = input.Substring(input.IndexOf("(") +1, input.IndexOf(")")- input.IndexOf("(")- 1);

1

Regex kullanmaktan kaçınan genel amaçlı okunabilir bir fonksiyon:

// Returns the text between 'start' and 'end'.
string ExtractBetween(string text, string start, string end)
{
  int iStart = text.IndexOf(start);
  iStart = (iStart == -1) ? 0 : iStart + start.Length;
  int iEnd = text.LastIndexOf(end);
  if(iEnd == -1)
  {
    iEnd = text.Length;
  }
  int len = iEnd - iStart;

  return text.Substring(iStart, len);
}

Özel örneğinizde aramak için şunları yapabilirsiniz:

string result = ExtractBetween("User name (sales)", "(", ")");

1

Düzenli ifadelerin son derece yararlı olduğunu ancak yazmanın çok zor olduğunu düşünüyorum. Bu yüzden biraz araştırma yaptım ve yazmayı çok kolaylaştıran bu aracı buldum .

Onlardan uzak durmayın çünkü sözdiziminin anlaşılması zordur. Çok güçlü olabilirler.


2
SO hoş geldiniz! Bu iyi bir tavsiye, ama cevap olarak gönderilmemeliydi. Bunun gibi genel tavsiyeler, eğer varsa, yorum olarak gönderilmelidir. Bir cevap, sorucunun özel sorununu ele almalıdır. Henüz yorum yazmak için yeterli itibar puanınız olmadığını biliyorum, ancak tam olarak bu yüzden eşik eşiği var. Biraz daha uzun süre bulunduğunuzda, insanların her zaman Rubular gibi araçlar önerdiğini göreceksiniz (elbette yorumlarda). Başka bir deyişle, bu tavsiye faydalı olabilir, ancak acil değildir.
Alan Moore

0

Çok benzer bir uygulamaya bir çözüm ararken buna rastladım.

İşte gerçek kodumdan bir pasaj. Alt karakter dizisini ilk karakterden başlatır (dizin 0).

 string separator = "\n";     //line terminator

 string output;
 string input= "HowAreYou?\nLets go there!";

 output = input.Substring(0, input.IndexOf(separator)); 

Bu OP'nin sorduğu sorulara cevap vermez.
dicemaster

0

Bu kod, buradaki çoğu çözümden daha hızlıdır (hepsi değilse de), Dize uzantısı yöntemi olarak paketlenmiştir , özyinelemeli yuvalamayı desteklemez:

public static string GetNestedString(this string str, char start, char end)
{
    int s = -1;
    int i = -1;
    while (++i < str.Length)
        if (str[i] == start)
        {
            s = i;
            break;
        }
    int e = -1;
    while(++i < str.Length)
        if (str[i] == end)
        {
            e = i;
            break;
        }
    if (e > s)
        return str.Substring(s + 1, e - s - 1);
    return null;
}

Bu biraz daha uzun ve yavaş, ancak özyinelemeli yuvalamayı daha güzel idare ediyor:

public static string GetNestedString(this string str, char start, char end)
{
    int s = -1;
    int i = -1;
    while (++i < str.Length)
        if (str[i] == start)
        {
            s = i;
            break;
        }
    int e = -1;
    int depth = 0;
    while (++i < str.Length)
        if (str[i] == end)
        {
            e = i;
            if (depth == 0)
                break;
            else
                --depth;
        }
        else if (str[i] == start)
            ++depth;
    if (e > s)
        return str.Substring(s + 1, e - s - 1);
    return null;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.