Eu tenho uma string como:
"super exemple of string key : text I want to keep - end of my string"
Eu quero apenas manter a corda que está entre "key : "e " - ". Como eu posso fazer isso? Devo usar um Regex ou posso fazer de outra maneira?
Eu tenho uma string como:
"super exemple of string key : text I want to keep - end of my string"
Eu quero apenas manter a corda que está entre "key : "e " - ". Como eu posso fazer isso? Devo usar um Regex ou posso fazer de outra maneira?
Respostas:
Talvez, uma boa maneira seja apenas cortar uma substring :
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;
ou apenas com operações de string
var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);
Você pode fazer isso sem regex
input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
.Split('-')[0]
.Trim();
Dependendo de quão robusta / flexível você deseja que sua implementação seja, isso pode ser um pouco complicado. Esta é a implementação que uso:
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 "
InvariantCulturenão está funcionando com o Windows Universal Apps. Existe alguma maneira de removê-lo mantendo a funcionalidade de sua classe? @ChaseMedallion
Aqui está a maneira como eu posso fazer isso
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;
}
Eu acho que isso funciona:
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 é um exagero aqui.
Você poderia usar string.Splitcom a sobrecarga que exige um string[]para os delimitadores, mas isso também seria um exagero.
Olhe para Substringe IndexOf- o primeiro para obter partes de uma string fornecida e indexe um comprimento e o segundo para localizar strings / caracteres internos indexados.
string.Split.
Uma solução LINQ funcional:
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);
Como o :e o -são exclusivos, você pode usar:
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];
ou, com um 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;
com um exemplo em execução .
Você pode decidir se é um exagero.
como um método de extensão validado
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;
}
}
Você pode usar o método de extensão abaixo:
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;
}
O uso é:
var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");
Usei o trecho de código de Vijay Singh Rana que basicamente faz o trabalho. Mas causará problemas se o firstStringjá contiver o lastString. O que eu queria era extrair um access_token de uma resposta JSON (sem JSON Parser carregado). Meu firstStringera \"access_token\": \"e meu lastStringera \". Acabei com uma pequena modificação
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 você está procurando uma solução de 1 linha, é isso:
s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()
A solução completa de 1 linha, com 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());
}
}
Você já tem algumas respostas boas e percebo que o código que estou fornecendo está longe de ser o mais eficiente e limpo. No entanto, pensei que poderia ser útil para fins educacionais. Podemos usar classes e bibliotecas pré-construídas o dia todo. Mas, sem entender o funcionamento interno, estamos simplesmente imitando e repetindo e nunca aprenderemos nada. Este código funciona e é mais básico ou "virgem" do que alguns dos outros:
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;
}
Você acaba com a string desejada atribuída à variável parsedString. Lembre-se de que ele também capturará espaços anteriores e anteriores. Lembre-se de que uma string é simplesmente uma matriz de caracteres que pode ser manipulada como outras matrizes com índices etc.
Cuidar.
Se você deseja lidar com várias ocorrências de pares de substring, não será fácil sem RegEx:
Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
input ?? String.Emptyevita argumento de exceção nula?=mantém a 1ª substring e?<=mantém a 2ª substringRegexOptions.Singlelinepermite nova linha entre par de substring
Se a ordem e a contagem de ocorrências de substrings não importam, esta rápida e suja pode ser uma opção:
var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;
Pelo menos evita a maioria das exceções, retornando a string original se nenhuma / única substring corresponder.
Como sempre digo, nada é impossível:
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);
}
Lembre-se de que deve adicionar referência de System.Text.RegularExpressions
Espero ter ajudado.
Algo assim talvez
private static string Between(string text, string from, string to)
{
return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}
Quando as perguntas são formuladas em termos de um único exemplo, as ambigüidades estão inevitavelmente presentes. Esta questão não é exceção.
Para o exemplo dado na pergunta, a string desejada é clara:
super example of string key : text I want to keep - end of my string
^^^^^^^^^^^^^^^^^^^
No entanto, essa string é apenas um exemplo de strings e strings de limite para as quais certas substrings devem ser identificadas. Vou considerar uma string genérica com strings de fronteira genéricas, representadas da seguinte maneira.
abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
^^^^^^^^^^^^ ^^^^^
PPé a string anterior , FFé a seguinte e os chapéus de festa indicam quais substrings devem ser combinadas. (No exemplo dado na pergunta key : é a string anterior e -é a seguinte.) Presumi que PPe FFsão precedidos e seguidos por limites de palavras (de modo que PPAe FF8não são correspondidos).
Minhas suposições, conforme refletidas pelos chapéus de festa, são as seguintes:
PPpode ser precedida por uma (ou mais) FFsubstrings, que, se presentes, são desconsideradas;PPfor seguido por um ou mais PPs antes de FFser encontrado, os seguintes PPs são parte da substring entre as strings anteriores e seguintes;PPfor seguido por um ou mais FFs antes de um PPencontro, o primeiro FFseguinte PPé considerado a seguinte string.Observe que muitas das respostas aqui tratam apenas de strings da forma
abc PP def FF ghi
^^^^^
ou
abc PP def FF ghi PP jkl FF mno
^^^^^ ^^^^^
Pode-se usar uma expressão regular, construções de código ou uma combinação dos dois para identificar as substrings de interesse. Não faço nenhum julgamento sobre qual abordagem é a melhor. Apresentarei apenas a seguinte expressão regular que corresponderá às substrings de interesse.
(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)
Eu testei isso com o mecanismo regex PCRE (PHP), mas como o regex não é exótico, tenho certeza de que funcionará com o mecanismo regex .NET (que é muito robusto).
O mecanismo regex executa as seguintes operações:
(?<= : 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
Esta técnica, de casar um caractere por vez, seguindo a string precedente, até que o caractere seja Fe seja seguido por F(ou mais geralmente, o caractere crie a string que constitui a string seguinte), é chamada de Solução de Token Guloso Temperado .
Naturalmente, a regex teria que ser modificada (se possível) se as suposições que estabeleci acima forem alteradas.
1. Mova o cursor para obter explicações detalhadas.
Em C # 8.0 e acima, você pode usar o operador de intervalo ..como em
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
Consulte a documentação para obter detalhes.
substringeindexof