Come estraggo il testo tra parentesi (parentesi tonde)?


224

Ho una stringa User name (sales)e desidero estrarre il testo tra parentesi, come farei?

Ho il sospetto che la sottostringa non riesca a capire come leggere fino alla parentesi di chiusura, la lunghezza del testo varierà.


2
Mostraci cosa hai provato. Hai guardato usando le espressioni regolari?
George Stocker,

Risposte:


445

Se desideri stare lontano dalle espressioni regolari, il modo più semplice a cui riesco a pensare è:

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

91
Onestamente, questo avrebbe dovuto essere selezionato come risposta.
Pat Lindley,

1
Non sarà ulteriormente contratto in input.Split ("()". ToCharArray ()) [1]
prabhakaran,

14
e nel caso in cui si desideri utilizzare la stessa logica per selezionare multipli:var input = "(fdw) User name (sales) safdsdf (again?)"; var output = input.Split('(', ')').Where((item, index) => index % 2 != 0).ToList();
WtFudgE

1
attenzione che questa soluzione si estrae salesanche dalle stringhe di input contenenti )sales(, (sales(ecc.
Stefano Spinucci,

435

Un modo molto semplice per farlo è usare espressioni regolari:

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

Come risposta al commento (molto divertente), ecco lo stesso Regex con alcune spiegazioni:

\(             # 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
Adoro quando le persone dicono "un modo semplice è usare espressioni regolari" e quindi offrire ciò che equivale a una serie di geroglifici indecifrabili (è particolarmente divertente quando diverse persone suggeriscono regex e ognuna presenta un diverso set di geroglifici per lo stesso problema ). :)
Deltics,

47
Non ci sono abbastanza risposte sullo stack che spiegano effettivamente cosa sta succedendo. Grazie per la meravigliosa spiegazione.
Sandy Gifford,

Se stai usando "@" all'inizio penso che non sia necessario sfuggire alla parentesi?
grado 1 °

10
@ rank1 è necessario sfuggire alla parentesi. Ciò che @ offre qui è che non è necessario sfuggire alle barre rovesciate. Quindi senza @ sarebbe come "\\ (([^)] *) \\)".
Diadistis,

Questo non gestisce bene i gruppi nidificati. Modificato invar filterRegex = new Regex(Regex.Escape("(") + "([^()]*)" + Regex.Escape(")"));
Jan Van der Haegen il

91

Supponendo di avere solo una coppia di parentesi.

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

7
iniziare + 1 nella sottostringa è più corretto se si desidera "vendite" anziché (vendite)
Joze

1
che cosa accadrà happend s = "User) name (Sales)"?
dotnetstep,

@dotnetstep hai ragione dovrebbe essere int end = s.IndexOf(")", start);. Ho messo in coda una modifica ...
ChrisD,

1
"(" .Lunghezza; è meglio di +1. Ha inviato una modifica. Ha anche aggiunto una funzione.
Ave

24

Usa questa funzione:

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

e qui è l'uso:

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

e l'output sarebbe:

sales

16

Le espressioni regolari potrebbero essere lo strumento migliore qui. Se non hai familiarità con loro, ti consiglio di installare Expresso - un ottimo strumento regex.

Qualcosa di simile a:

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
Ovviamente dovresti calcolare la posizione della prima parentesi solo una volta.
Martin Brown,

Nel caso in cui tu abbia una parentesi interna, ad esempio, input = "User name (sales(1))potresti voler usare input.LastIndexOf(')')quale funzionerà se ci sono parentesi interne o meno.
Ben

13

Forse una regex? Penso che funzionerebbe ...

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

Usa un'espressione regolare:

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

Il regexmetodo è superiore credo, ma se si voleva utilizzare gli umilisubstring

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

o

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

1

Ecco una funzione leggibile per uso generale che evita l'uso di 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);
}

Per chiamarlo nel tuo esempio particolare puoi fare:

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

1

Sto scoprendo che le espressioni regolari sono estremamente utili ma molto difficili da scrivere. Quindi, ho fatto qualche ricerca e ho trovato questo strumento che semplifica la scrittura.

Non esitare da loro perché la sintassi è difficile da capire. Possono essere così potenti.


2
Benvenuti in SO! Questo è un buon consiglio, ma non avrebbe dovuto essere pubblicato come risposta. Consigli generali come questo dovrebbero essere pubblicati come commenti, se non del tutto. Una risposta deve affrontare il problema specifico del richiedente. So che non hai ancora abbastanza punti reputazione per pubblicare commenti, ma questo è esattamente il motivo per cui esiste la soglia di reputazione. Quando sarai in giro un po 'di più, vedrai che le persone raccomandano sempre strumenti come Rubular (nei commenti, ovviamente). In altre parole, questo consiglio può essere utile, ma non è urgente.
Alan Moore,

0

Mi sono imbattuto in questo mentre cercavo una soluzione per un'implementazione molto simile.

Ecco uno snippet dal mio codice attuale. Inizia la sottostringa dal primo carattere (indice 0).

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

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

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

Questo non risponde a ciò che l'OP ha chiesto.
dicemaster,

0

Questo codice è più veloce della maggior parte delle soluzioni qui (se non tutte), compresso come metodo di estensione String , non supporta l'annidamento ricorsivo:

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

Questo è un po 'più lungo e più lento, ma gestisce più facilmente l'annidamento ricorsivo:

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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.