Mam taki ciąg:
"super exemple of string key : text I want to keep - end of my string"
Chcę po prostu zachować ciąg znajdujący się między "key : "
a " - "
. Jak mogę to zrobić? Czy muszę używać Regex, czy mogę to zrobić w inny sposób?
Mam taki ciąg:
"super exemple of string key : text I want to keep - end of my string"
Chcę po prostu zachować ciąg znajdujący się między "key : "
a " - "
. Jak mogę to zrobić? Czy muszę używać Regex, czy mogę to zrobić w inny sposób?
Odpowiedzi:
Być może dobrym sposobem jest po prostu wycięcie podciągu :
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;
lub tylko z operacjami na łańcuchach
var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);
Możesz to zrobić bez wyrażenia regularnego
input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
.Split('-')[0]
.Trim();
W zależności od tego, jak solidna / elastyczna ma być Twoja implementacja, może to być trochę trudne. Oto implementacja, której używam:
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
nie działa z aplikacjami uniwersalnymi systemu Windows. Czy jest jakiś sposób, aby go usunąć, zachowując funkcjonalność swojej klasy? @ChaseMedallion
Oto sposób, w jaki mogę to zrobić
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;
}
Myślę, że to działa:
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 to przesada.
Państwo mogli korzystać string.Split
z przeciążeniem, które odbywają się string[]
na ograniczniki ale to też być przesadą.
Spójrz na Substring
i IndexOf
- pierwsze, aby uzyskać części podanego ciągu i indeksu oraz długość, a drugie, aby znaleźć indeksowane wewnętrzne ciągi / znaki.
string.Split
.
Działające rozwiązanie LINQ:
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);
Ponieważ :
i -
są unikalne, możesz użyć:
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];
lub z wyrażeniem regularnym.
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;
Możesz zdecydować, czy to przesada.
jako niedostatecznie zwalidowana metoda rozszerzenia
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;
}
}
Możesz skorzystać z poniższej metody rozszerzenia:
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;
}
Wykorzystanie to:
var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");
Użyłem fragmentu kodu z Vijay Singh Rana, który w zasadzie spełnia swoje zadanie. Ale powoduje problemy, jeśli firstString
plik zawiera już rozszerzenie lastString
. Chciałem wyodrębnić access_token z odpowiedzi JSON (nie załadowano parsera JSON). Moje firstString
było \"access_token\": \"
i moje lastString
było \"
. Skończyło się na niewielkiej modyfikacji
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);
}
Jeśli szukasz rozwiązania 1-liniowego, oto jest:
s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()
Całe rozwiązanie 1-liniowe z 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());
}
}
Masz już kilka dobrych odpowiedzi i zdaję sobie sprawę, że kod, który dostarczam, jest daleki od najbardziej wydajnego i czystego. Pomyślałem jednak, że może to być przydatne do celów edukacyjnych. Możemy używać gotowych klas i bibliotek przez cały dzień. Ale bez zrozumienia wewnętrznego działania po prostu naśladujemy i powtarzamy i nigdy się niczego nie nauczymy. Ten kod działa i jest bardziej podstawowy lub „dziewiczy” niż niektóre inne:
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;
}
Kończysz z żądanym ciągiem przypisanym do zmiennej parsedString. Należy pamiętać, że przechwytuje również pola poprzedzające i poprzedzające. Pamiętaj, że ciąg to po prostu tablica znaków, którymi można manipulować jak innymi tablicami z indeksami itp.
Dbać.
Jeśli chcesz obsłużyć wiele wystąpień par podciągów, nie będzie to łatwe bez wyrażenia regularnego:
Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
input ?? String.Empty
unika wyjątku zerowego argumentu?=
zachowuje pierwszy podciąg i?<=
zachowuje drugi podciągRegexOptions.Singleline
dopuszcza znak nowej linii między parą podciągów
Jeśli kolejność i liczba wystąpień podciągów nie ma znaczenia, ten szybki i brudny może być opcją:
var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;
Przynajmniej unika większości wyjątków, zwracając oryginalny ciąg, jeśli żaden / pojedynczy podciąg nie pasuje.
Jak zawsze powtarzam, nie ma rzeczy niemożliwych:
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);
}
Pamiętaj, że powinno dodać odwołanie do System.Text.RegularExpressions
Mam nadzieję, że pomogłem.
Może coś takiego
private static string Between(string text, string from, string to)
{
return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}
Gdy pytania są zadawane w kategoriach pojedynczego przykładu, nieuchronnie pojawiają się niejasności. To pytanie nie jest wyjątkiem.
Dla przykładu podanego w pytaniu pożądany ciąg jest jasny:
super example of string key : text I want to keep - end of my string
^^^^^^^^^^^^^^^^^^^
Jednak ten ciąg jest tylko przykładem łańcuchów i ciągów granicznych, dla których mają zostać zidentyfikowane określone podciągi. Rozważę ogólny ciąg z ogólnymi łańcuchami granicznymi, przedstawionymi w następujący sposób.
abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
^^^^^^^^^^^^ ^^^^^
PP
jest poprzedzającym ciągiem , FF
jest następującym ciągiem, a kapelusze imprezowe wskazują, które podciągi mają zostać dopasowane. (W przykładzie podanym w pytaniu key :
jest poprzedzający ciąg i -
jest to następujący ciąg.) Założyłem to PP
i FF
są poprzedzone i zakończone granicami słów (tak, że PPA
i FF8
nie są dopasowane).
Moje założenia, które odzwierciedlają czapki imprezowe, są następujące:
PP
może być poprzedzony jednym (lub więcej) FF
podciągami, które, jeśli są obecne, są pomijane;PP
następuje jedno lub więcej PP
s przed FF
napotkaniem, następujące PP
s są częścią podłańcucha między poprzedzającym a następnym ciągiem;PP
następuje jedno lub więcej FF
s przed PP
spotkaniem, pierwszy FF
następujący po nim PP
jest uważany za następujący ciąg.Zwróć uwagę, że wiele odpowiedzi tutaj dotyczy tylko ciągów znaków formularza
abc PP def FF ghi
^^^^^
lub
abc PP def FF ghi PP jkl FF mno
^^^^^ ^^^^^
Można użyć wyrażenia regularnego, konstrukcji kodu lub kombinacji tych dwóch w celu zidentyfikowania interesujących nas podciągów. Nie oceniam, które podejście jest najlepsze. Przedstawię tylko następujące wyrażenie regularne, które będzie pasowało do interesujących nas podciągów.
(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)
Przetestowałem to z silnikiem regex PCRE (PHP), ale ponieważ wyrażenie regularne wcale nie jest egzotyczne, jestem pewien, że będzie działać z silnikiem regex .NET (który jest bardzo solidny).
Silnik wyrażeń regularnych wykonuje następujące operacje:
(?<= : 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
Ta technika polega na dopasowywaniu jednego znaku na raz, po poprzedzającym ciągu, aż do znaku F
i następuje po nimF
(lub bardziej ogólnie, znak jest łańcuchem, który tworzy następujący ciąg), nazywa się Tempered Greedy Token Solution .
Oczywiście regex musiałby zostać zmodyfikowany (jeśli to możliwe), gdyby zmienione zostały założenia, które przedstawiłem powyżej.
1. Poruszaj kursorem, aby uzyskać szczegółowe wyjaśnienia.
W C # 8,0 i nowszych można użyć operatora zakresu, ..
tak jak w
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
Szczegółowe informacje można znaleźć w dokumentacji .
substring
iindexof