Ho una stringa come:
"super exemple of string key : text I want to keep - end of my string"
Voglio solo mantenere la stringa che si trova tra "key : "
e " - "
. Come lo posso fare? Devo usare una Regex o posso farlo in un altro modo?
Ho una stringa come:
"super exemple of string key : text I want to keep - end of my string"
Voglio solo mantenere la stringa che si trova tra "key : "
e " - "
. Come lo posso fare? Devo usare una Regex o posso farlo in un altro modo?
Risposte:
Forse, un buon modo è semplicemente tagliare una sottostringa :
String St = "super exemple of string key : text I want to keep - end of my string";
int pFrom = St.IndexOf("key : ") + "key : ".Length;
int pTo = St.LastIndexOf(" - ");
String result = St.Substring(pFrom, pTo - pFrom);
string input = "super exemple of string key : text I want to keep - end of my string";
var match = Regex.Match(input, @"key : (.+?)-").Groups[1].Value;
o solo con operazioni sulle stringhe
var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);
Puoi farlo senza regex
input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
.Split('-')[0]
.Trim();
A seconda di quanto robusta / flessibile vuoi che sia la tua implementazione, questo può effettivamente essere un po 'complicato. Ecco l'implementazione che utilizzo:
public static class StringExtensions {
/// <summary>
/// takes a substring between two anchor strings (or the end of the string if that anchor is null)
/// </summary>
/// <param name="this">a string</param>
/// <param name="from">an optional string to search after</param>
/// <param name="until">an optional string to search before</param>
/// <param name="comparison">an optional comparison for the search</param>
/// <returns>a substring based on the search</returns>
public static string Substring(this string @this, string from = null, string until = null, StringComparison comparison = StringComparison.InvariantCulture)
{
var fromLength = (from ?? string.Empty).Length;
var startIndex = !string.IsNullOrEmpty(from)
? @this.IndexOf(from, comparison) + fromLength
: 0;
if (startIndex < fromLength) { throw new ArgumentException("from: Failed to find an instance of the first anchor"); }
var endIndex = !string.IsNullOrEmpty(until)
? @this.IndexOf(until, startIndex, comparison)
: @this.Length;
if (endIndex < 0) { throw new ArgumentException("until: Failed to find an instance of the last anchor"); }
var subString = @this.Substring(startIndex, endIndex - startIndex);
return subString;
}
}
// usage:
var between = "a - to keep x more stuff".Substring(from: "-", until: "x");
// returns " to keep "
InvariantCulture
non funziona con le app universali di Windows. C'è un modo per rimuoverlo mantenendo la funzionalità della tua classe? @ChaseMedallion
Ecco come posso farlo
public string Between(string STR , string FirstString, string LastString)
{
string FinalString;
int Pos1 = STR.IndexOf(FirstString) + FirstString.Length;
int Pos2 = STR.IndexOf(LastString);
FinalString = STR.Substring(Pos1, Pos2 - Pos1);
return FinalString;
}
Penso che funzioni:
static void Main(string[] args)
{
String text = "One=1,Two=2,ThreeFour=34";
Console.WriteLine(betweenStrings(text, "One=", ",")); // 1
Console.WriteLine(betweenStrings(text, "Two=", ",")); // 2
Console.WriteLine(betweenStrings(text, "ThreeFour=", "")); // 34
Console.ReadKey();
}
public static String betweenStrings(String text, String start, String end)
{
int p1 = text.IndexOf(start) + start.Length;
int p2 = text.IndexOf(end, p1);
if (end == "") return (text.Substring(p1));
else return text.Substring(p1, p2 - p1);
}
Regex è eccessivo qui.
Si potrebbe utilizzare string.Split
con il sovraccarico che prende una string[]
per i delimitatori ma che sarebbe anche essere eccessivo.
Guarda Substring
e IndexOf
- il primo per ottenere parti di una stringa data e indice e una lunghezza e il secondo per trovare indicizzati stringhe / caratteri interni.
string.Split
.
Una soluzione LINQ funzionante:
string str = "super exemple of string key : text I want to keep - end of my string";
string res = new string(str.SkipWhile(c => c != ':')
.Skip(1)
.TakeWhile(c => c != '-')
.ToArray()).Trim();
Console.WriteLine(res); // text I want to keep
string str="super exemple of string key : text I want to keep - end of my string";
int startIndex = str.IndexOf("key") + "key".Length;
int endIndex = str.IndexOf("-");
string newString = str.Substring(startIndex, endIndex - startIndex);
Poiché i :
e -
sono unici, potresti usare:
string input;
string output;
input = "super example of string key : text I want to keep - end of my string";
output = input.Split(new char[] { ':', '-' })[1];
o, con una regex.
using System.Text.RegularExpressions;
...
var value =
Regex.Match(
"super exemple of string key : text I want to keep - end of my string",
"key : (.*) - ")
.Groups[1].Value;
con un esempio in esecuzione .
Puoi decidere se è eccessivo.
come metodo di estensione sottovalutato
using System.Text.RegularExpressions;
public class Test
{
public static void Main()
{
var value =
"super exemple of string key : text I want to keep - end of my string"
.Between(
"key : ",
" - ");
Console.WriteLine(value);
}
}
public static class Ext
{
static string Between(this string source, string left, string right)
{
return Regex.Match(
source,
string.Format("{0}(.*){1}", left, right))
.Groups[1].Value;
}
}
Puoi utilizzare il metodo di estensione di seguito:
public static string GetStringBetween(this string token, string first, string second)
{
if (!token.Contains(first)) return "";
var afterFirst = token.Split(new[] { first }, StringSplitOptions.None)[1];
if (!afterFirst.Contains(second)) return "";
var result = afterFirst.Split(new[] { second }, StringSplitOptions.None)[0];
return result;
}
L'utilizzo è:
var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");
Ho usato lo snippet di codice di Vijay Singh Rana che fondamentalmente fa il lavoro. Ma causa problemi se il file firstString
contiene già il file lastString
. Quello che volevo era estrarre un access_token da una risposta JSON (nessun Parser JSON caricato). Il mio firstString
era \"access_token\": \"
e il mio lastString
era \"
. Ho finito con una piccola modifica
string Between(string str, string firstString, string lastString)
{
int pos1 = str.IndexOf(firstString) + firstString.Length;
int pos2 = str.Substring(pos1).IndexOf(lastString);
return str.Substring(pos1, pos2);
}
Se stai cercando una soluzione a 1 linea, questa è:
s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()
L'intera soluzione a 1 linea, con System.Linq
:
using System;
using System.Linq;
class OneLiner
{
static void Main()
{
string s = "TextHereTisImortant973End"; //Between "eT" and "97"
Console.WriteLine(s.Substring(s.IndexOf("eT") + "eT".Length)
.Split("97".ToCharArray()).First());
}
}
Hai già alcune buone risposte e mi rendo conto che il codice che sto fornendo è tutt'altro che il più efficiente e pulito. Tuttavia, ho pensato che potrebbe essere utile per scopi educativi. Possiamo usare classi e librerie predefinite tutto il giorno. Ma senza comprendere il funzionamento interno, stiamo semplicemente imitando e ripetendo e non impareremo mai nulla. Questo codice funziona ed è più semplice o "vergine" di alcuni degli altri:
char startDelimiter = ':';
char endDelimiter = '-';
Boolean collect = false;
string parsedString = "";
foreach (char c in originalString)
{
if (c == startDelimiter)
collect = true;
if (c == endDelimiter)
collect = false;
if (collect == true && c != startDelimiter)
parsedString += c;
}
Si finisce con la stringa desiderata assegnata alla variabile parsedString. Tieni presente che acquisirà anche gli spazi precedenti e precedenti. Ricorda che una stringa è semplicemente un array di caratteri che può essere manipolato come altri array con indici ecc.
Stai attento.
Se vuoi gestire più occorrenze di coppie di sottostringhe, non sarà facile senza RegEx:
Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
input ?? String.Empty
evita l'eccezione nulla dell'argomento?=
mantiene la prima sottostringa e la?<=
seconda sottostringaRegexOptions.Singleline
consente la nuova riga tra la coppia di sottostringhe
Se il conteggio degli ordini e delle occorrenze delle sottostringhe non è importante, questo veloce e sporco potrebbe essere un'opzione:
var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;
Almeno evita la maggior parte delle eccezioni, restituendo la stringa originale se nessuna / singola sottostringa corrisponde.
Come dico sempre niente è impossibile:
string value = "super exemple of string key : text I want to keep - end of my string";
Regex regex = new Regex(@"(key \: (.*?) _ )");
Match match = regex.Match(value);
if (match.Success)
{
Messagebox.Show(match.Value);
}
Ricorda che dovrebbe aggiungere il riferimento a System.Text.RegularExpressions
Spero di aver aiutato.
Qualcosa di simile forse
private static string Between(string text, string from, string to)
{
return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}
Quando le domande sono espresse in termini di un unico esempio, inevitabilmente sono presenti ambiguità. Questa domanda non fa eccezione.
Per l'esempio fornito nella domanda la stringa desiderata è chiara:
super example of string key : text I want to keep - end of my string
^^^^^^^^^^^^^^^^^^^
Tuttavia, questa stringa non è che un esempio di stringhe e stringhe limite per le quali devono essere identificate determinate sottostringhe. Prenderò in considerazione una stringa generica con stringhe di confine generiche, rappresentate come segue.
abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
^^^^^^^^^^^^ ^^^^^
PP
è la stringa precedente , FF
è la stringa seguente e i cappelli da festa indicano quali sottostringhe devono essere abbinate. (Nell'esempio fornito nella domanda key :
è la stringa precedente ed -
è la stringa seguente.) Ho assunto che PP
e FF
siano preceduti e seguiti da confini di parola (in modo che PPA
e FF8
non siano trovati).
Le mie ipotesi, come riflettono i cappelli da festa, sono le seguenti:
PP
può essere preceduta da una (o più) FF
sottostringhe, che, se presenti, vengono ignorate;PP
è seguito da uno o più messaggi PP
prima, FF
viene rilevato quanto seguePP
fanno parte della sottostringa tra la stringa precedente e quella successiva;PP
è seguito da uno o più FF
s prima che un PP
sia incontrato, il primo che FF
segue PP
è considerato la stringa seguente.Notare che molte delle risposte qui trattano solo le stringhe del modulo
abc PP def FF ghi
^^^^^
o
abc PP def FF ghi PP jkl FF mno
^^^^^ ^^^^^
Si può usare un'espressione regolare, costrutti di codice o una combinazione dei due per identificare le sottostringhe di interesse. Non giudico l'approccio migliore. Presenterò solo la seguente espressione regolare che corrisponderà alle sottostringhe di interesse.
(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)
L'ho testato con il motore regex PCRE (PHP), ma poiché la regex non è affatto esotica, sono sicuro che funzionerà con il motore regex .NET (che è molto robusto).
Il motore regex esegue le seguenti operazioni:
(?<= : begin a positive lookbehind
\bPP\b : match 'PP'
) : end positive lookbehind
(?: : begin a non-capture group
(?! : begin a negative lookahead
\bFF\b : match 'FF'
) : end negative lookahead
. : match any character
) : end non-capture group
* : execute non-capture group 0+ times
(?= : begin positive lookahead
\bFF\b : match 'FF'
) : end positive lookahead
Questa tecnica, di abbinare un carattere alla volta, seguendo la stringa precedente, finché il carattere non è F
ed è seguito da F
(o più in generale, il carattere inizia la stringa che costituisce la stringa successiva), è chiamata Tempered Greedy Token Solution .
Naturalmente, la regex dovrebbe essere modificata (se possibile) se le ipotesi che ho esposto sopra vengono modificate.
1. Spostare il cursore per ottenere spiegazioni dettagliate.
In C # 8.0 e versioni successive è possibile utilizzare l'operatore di intervallo ..
come in
var s = "header-THE_TARGET_STRING.7z";
var from = s.IndexOf("-") + "-".Length;
var to = s.IndexOf(".7z");
var versionString = s[from..to]; // THE_TARGET_STRING
Vedere la documentazione per i dettagli.
substring
eindexof