Làm cách nào để trích xuất văn bản nằm giữa dấu ngoặc đơn (dấu ngoặc tròn)?


224

Tôi có một chuỗi User name (sales)và tôi muốn trích xuất văn bản giữa các dấu ngoặc, tôi sẽ làm điều này như thế nào?

Tôi nghi ngờ chuỗi con nhưng tôi không thể tìm ra cách đọc cho đến khi khung đóng, độ dài của văn bản sẽ thay đổi.


2
Cho chúng tôi thấy những gì bạn đã cố gắng. Bạn đã xem xét sử dụng biểu thức thông thường?
George Stocker

Câu trả lời:


445

Nếu bạn muốn tránh xa các biểu thức thông thường, cách đơn giản nhất tôi có thể nghĩ đến là:

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

91
Thành thật mà nói, điều này nên được chọn là câu trả lời.
Pat Lindley

1
Không phải nó sẽ được ký hợp đồng thêm vào đầu vào.Split ("()". ToCharArray ()) [1]
prabhakaran

14
và trong trường hợp bạn muốn sử dụng cùng một logic để chọn nhiều:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
hãy cẩn thận rằng giải pháp này salescũng trích xuất từ các chuỗi đầu vào có chứa )sales(, (sales(v.v.
Stefano Spinucci

435

Một cách rất đơn giản để làm điều đó là sử dụng các biểu thức thông thường:

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

Để trả lời cho nhận xét (rất buồn cười), đây là Regex tương tự với một số giải thích:

\(             # 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
Tôi thích nó khi mọi người nói "một cách đơn giản là sử dụng các biểu thức chính quy" và sau đó cung cấp số tiền cho một chuỗi chữ tượng hình không thể giải mã được (điều này đặc biệt thú vị khi những người khác nhau đề xuất regex và mỗi người đưa ra một bộ chữ tượng hình khác nhau cho cùng một vấn đề ). :)
Phân tích

47
Không có đủ câu trả lời trên stack mà thực sự giải thích những gì đang diễn ra. Cảm ơn bạn đã giải thích tuyệt vời.
Sandy Gifford

Nếu bạn đang sử dụng '@' khi bắt đầu, tôi nghĩ Bạn không cần phải thoát dấu ngoặc đơn?
xếp hạng1

10
@ rank1 bạn phải thoát dấu ngoặc đơn. Những gì @ cung cấp ở đây là bạn không cần phải thoát khỏi dấu gạch chéo ngược. Vì vậy, nếu không có @, nó sẽ giống như "\\ (([^)] *) \\)".
Diadistis

Điều này không xử lý tốt các nhóm lồng nhau mặc dù. Đổi thànhvar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen

91

Giả sử rằng bạn chỉ có một cặp dấu ngoặc đơn.

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

7
bắt đầu + 1 trong chuỗi là chính xác hơn nếu bạn muốn "bán hàng" thay vì (sales)
Jože

1
Điều gì sẽ xảy ra với s = "Tên người dùng (Bán hàng)"?
dotnetstep

@dotnetstep bạn đúng int end = s.IndexOf(")", start);. Tôi đã xếp hàng chỉnh sửa ...
ChrisD

1
"(". Chiều dài; tốt hơn +1. Đã gửi một chỉnh sửa. Cũng đã thêm một chức năng.
Ave

24

Sử dụng chức năng này:

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

và đây là cách sử dụng:

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

và đầu ra sẽ là:

sales

16

Biểu thức chính quy có thể là công cụ tốt nhất ở đây. Nếu bạn không quen thuộc với họ, tôi khuyên bạn nên cài đặt Expresso - một công cụ regex nhỏ tuyệt vời.

Cái gì đó như:

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
Tất nhiên bạn chỉ nên tính toán vị trí của khung đầu tiên một lần.
Martin Brown

Trong trường hợp bạn có dấu ngoặc đơn bên trong, ví dụ input = "User name (sales(1))bạn có thể muốn sử dụng input.LastIndexOf(')')nó sẽ hoạt động nếu có dấu ngoặc đơn bên trong hay không.
Ben

13

Một regex có thể? Tôi nghĩ rằng điều này sẽ làm việc ...

\(([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

Sử dụng biểu thức chính quy:

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

Các regexphương pháp ưu việt hơn tôi nghĩ, nhưng nếu bạn muốn sử dụng khiêm tốnsubstring

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

hoặc là

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

1

Đây là một chức năng có thể đọc được nhằm mục đích chung tránh sử dụng regex:

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

Để gọi nó trong ví dụ cụ thể của bạn, bạn có thể làm:

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

1

Tôi thấy rằng các biểu thức chính quy cực kỳ hữu ích nhưng rất khó viết. Vì vậy, tôi đã làm một số nghiên cứu và tìm thấy công cụ này làm cho việc viết chúng trở nên dễ dàng.

Đừng né tránh chúng vì cú pháp rất khó để tìm ra. Họ có thể rất mạnh mẽ.


2
Chào mừng đến với SO! Đây là lời khuyên tốt, nhưng nó không nên được đăng lên như một câu trả lời. Lời khuyên chung như thế này nên được đăng dưới dạng bình luận, nếu có. Một câu trả lời phải giải quyết vấn đề cụ thể của người hỏi. Tôi biết bạn chưa có đủ điểm danh tiếng để đăng bình luận, nhưng đây chính xác là lý do tại sao ngưỡng đại diện tồn tại. Khi bạn ở đây lâu hơn một chút, bạn sẽ thấy rằng mọi người luôn đề xuất các công cụ như Rubular (tất nhiên là trong các bình luận). Nói cách khác, lời khuyên này có thể hữu ích, nhưng nó không khẩn cấp.
Alan Moore

0

Tôi đã bắt gặp điều này trong khi tôi đang tìm kiếm một giải pháp cho việc thực hiện rất giống nhau.

Đây là một đoạn từ mã thực tế của tôi. Bắt đầu chuỗi con từ char đầu tiên (chỉ số 0).

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

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

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

Điều này không trả lời những gì OP đã yêu cầu.
dicemaster

0

Mã này nhanh hơn hầu hết các giải pháp ở đây (nếu không phải tất cả), được đóng gói như phương thức mở rộng Chuỗi , nó không hỗ trợ lồng nhau đệ quy:

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

Cái này dài hơn một chút và chậm hơn, nhưng nó xử lý việc lồng đệ quy độc đáo hơn:

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.