एक तार में दो तारों के बीच स्ट्रिंग प्राप्त करें


103

मेरे पास एक स्ट्रिंग है जैसे:

"super exemple of string key : text I want to keep - end of my string"

मैं सिर्फ स्ट्रिंग जो बीच में है रखना चाहते हैं "key : "और " - "। मैं उसे कैसे कर सकता हूँ? मुझे रेगेक्स का उपयोग करना चाहिए या क्या मैं इसे दूसरे तरीके से कर सकता हूं?


2
का उपयोग करें substringऔरindexof
Sayse

एक स्ट्रिंग में एक विशेष स्ट्रिंग के बाद और दूसरी विशिष्ट स्ट्रिंग से पहले स्ट्रिंग प्राप्त करें जो स्ट्रिंग में भी निहित है जहां पूर्व स्ट्रिंग है ..
केन किं

जवाबों:


161

शायद, एक अच्छा तरीका सिर्फ एक बाहर कटौती करने के लिए है सबस्ट्रिंग :

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

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

या सिर्फ स्ट्रिंग ऑपरेशन के साथ

var start = input.IndexOf("key : ") + 6;
var match2 = input.Substring(start, input.IndexOf("-") - start);

29

आप इसे रेगेक्स के बिना कर सकते हैं

 input.Split(new string[] {"key :"},StringSplitOptions.None)[1]
      .Split('-')[0]
      .Trim();

6
यह स्मृति में कई अनावश्यक तार पैदा करेगा। यदि आप स्मृति की परवाह करते हैं तो इसका उपयोग न करें।
मिकेल डूई बोलिंदर

14

आप अपने कार्यान्वयन को कितना मजबूत / लचीला चाहते हैं, इसके आधार पर, यह वास्तव में थोड़ा मुश्किल हो सकता है। यहाँ कार्यान्वयन मैं उपयोग कर रहा हूँ:

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 "

मैंने आपके कोड का उपयोग किया है, लेकिन मुझे nd AB जैसे स्ट्रिंग्स से @ this.IndexOf (जब तक, startIndex + fromLength, तुलना) पर एक छोटा सा बग मिल गया है, जहां A से है और B से है, तो मैंने + से लेनोवो को हटा दिया। मैंने हालांकि इसका गहराई से परीक्षण नहीं किया है
एड्रियन इफोड

1
@ AdrianIftode: अच्छी कॉल। यह निश्चित रूप से एक बग था। यह समझ में आता है कि दूसरे एंकर की खोज शुरू करें, क्योंकि वह पहले एंकर के अंत से पहले है। मैंने यहां कोड तय किया है।
चेसमेडलियन

InvariantCultureविंडोज यूनिवर्सल ऐप्स के साथ काम नहीं कर रहा है। क्या आपकी कक्षा की कार्यक्षमता को बनाए रखने के साथ इसे हटाने का कोई तरीका है? @ कैशेमेडियन
लियोन

@ एलोन: आपको सभी संस्कृति से संबंधित सामानों को चीरना चाहिए और .NET केवल अनुक्रमित संचालन के लिए वर्तमान संस्कृति का उपयोग करेगा। हालांकि, मैं विंडोज यूनिवर्सल ऐप्स से परिचित नहीं हूं, इसलिए मैं पक्के तौर पर नहीं कह सकता।
चेसमैडियन

13

यहाँ तरीका है कि मैं ऐसा कैसे कर सकता हूँ

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

13

मुझे लगता है कि यह काम करता है:

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

महान समाधान। धन्यवाद!
arcee123

10

रेगेक्स यहां ओवरकिल है।

आप ओवरलोड के साथ उपयोग कर सकते हैं string.Splitजो कि string[]सीमांकक के लिए लेता है लेकिन यह भी ओवरकिल होगा।

देखें Substringऔर IndexOf- पूर्व को दिए गए एक स्ट्रिंग के कुछ हिस्सों और सूचकांक और एक लंबाई पाने के लिए और दूसरा आंतरिक तार / वर्णों के अनुक्रमित खोजने के लिए।


2
यह ओवरकिल नहीं है ... वास्तव में मैं कहूंगा कि सबस्ट्रिंग और इंडेक्सऑफ अंडरकिल हैं। मैं कहता हूँ कि string.Split सही है। रेगेक्स ओवरकिल है।
इट्नोटली।

2
यह ओवरकिल या अंडर-किलर होने की बात मूट है, क्योंकि इसका उत्तर रेगेक्स की तुलना में इसे करने के पोस्टर के अनुरोध को पूरा करता है।
कार्ल एंडरसन

2
@newStackExchangeInstance: यह भी विफल रहता है अगर "कुंजी:" से पहले एक "-" है। स्थानापन्न हाजिर है।
जोर्मेनो

@newStackExchangeInstance - मुझे विश्वास है कि वह बात कर रहा है string.Split
ऊद

7

एक काम 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

क्या यह केवल एकल-वर्ण प्लेसहोल्डर्स के लिए काम करता है?
beppe9000

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

1
आपके कोड के परिणामस्वरूप नए कॉलिंग की शुरुआत में कोलन वापस आ जाएगा।
tsells

5

के बाद से :और -अद्वितीय आप उपयोग कर सकते हैं:

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

यह उत्तर मौजूदा उत्तरों की पहले से ही बड़ी राशि के लिए कुछ भी सार्थक नहीं जोड़ता है।
19

4

या, एक रेगेक्स के साथ।

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;

एक चल उदाहरण के साथ

आप तय कर सकते हैं कि इसकी ओवरकिल है या नहीं।

या

एक मान्य एक्सटेंशन पद्धति के तहत

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

4
var matches = Regex.Matches(input, @"(?<=key :)(.+?)(?=-)");

यह केवल "कुंजी:" और निम्नलिखित "


3

आप नीचे विस्तार विधि का उपयोग कर सकते हैं:

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

उपयोग है:

var token = "super exemple of string key : text I want to keep - end of my string";
var keyValue = token.GetStringBetween("key : ", " - ");

3

मैंने विजय सिंह राणा से कोड स्निपेट का इस्तेमाल किया जो मूल रूप से काम करता है। लेकिन यह समस्याओं का कारण बनता है अगर firstStringपहले से ही शामिल है lastString। जो मैं चाहता था वह JSON रिस्पांस (कोई JSON पार्सर लोड) से एक access_token निकाल रहा था। मेरे firstStringथा \"access_token\": \"और मेरे lastStringथा \"। मैं थोड़ा संशोधन के साथ समाप्त हुआ

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

1
अतिरेक है। pos1 को pos2 में जोड़ा गया, और फिर pos2 से प्रतिस्थापित किया गया।
जैल

धन्यवाद, आप सही हैं। मैंने ऊपर का उदाहरण सही किया।
nvm-uli

2

यदि आप 1 लाइन समाधान की तलाश में हैं, तो यह है:

s.Substring(s.IndexOf("eT") + "eT".Length).Split("97".ToCharArray()).First()

पूरे 1 लाइन समाधान, के साथ 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());
    }
}

1

आपके पास पहले से ही कुछ अच्छे उत्तर हैं और मुझे पता है कि मैं जो कोड प्रदान कर रहा हूं वह सबसे कुशल और साफ है। हालाँकि, मैंने सोचा कि यह शैक्षिक उद्देश्यों के लिए उपयोगी हो सकता है। हम दिन भर पूर्व निर्मित कक्षाओं और पुस्तकालयों का उपयोग कर सकते हैं। लेकिन भीतर के कामकाज को समझने के बिना, हम केवल नकल और दोहरा रहे हैं और कभी भी कुछ नहीं सीखेंगे। यह कोड काम करता है और दूसरों की तुलना में अधिक बुनियादी या "वर्जिन" है:

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

आप अपने इच्छित स्ट्रिंग के साथ समाप्त हो गए हैं जिसे parsedString चर को सौंपा गया है। ध्यान रखें कि यह कार्यवाही और पूर्ववर्ती रिक्त स्थान पर भी कब्जा करेगा। याद रखें कि एक स्ट्रिंग केवल वर्णों की एक सरणी है जिसे अन्य ऐरे के साथ जोड़ दिया जा सकता है जैसे सूचकांक आदि।

ख्याल रखना।


यह सबसे अच्छा एल्गोरिथ्म है हालांकि स्ट्रिंग निर्माण में सबसे खराब है। प्रदान किए गए सभी जवाब जो रेगेक्स नहीं हैं - केवल स्ट्रिंग्स बनाने में ट्रिगर-खुश हैं लेकिन यह इस अर्थ में सबसे खराब है। यदि आपने इसे शुरू करने के लिए स्ट्रिंग के अंत में शुरुआत की है और इसे निकालने के लिए '' string.Substring '' का उपयोग किया है, तो यह सही होगा।
पाउलो मोरागडो

मैं सहमत हूँ। जैसा कि मैंने उल्लेख किया है, यह कुशल से बहुत दूर है। मैं इस एल्गोरिथ्म का उपयोग करने की अनुशंसा नहीं करूंगा। यह बस "" इसे नीचे डंप कर रहा है "ताकि वह निचले स्तर पर तारों को समझ सके। अगर वह बस काम करना चाहता है, तो उसके पास पहले से ही जवाब था कि वह हासिल करेगा।
फ्लाईनफ्लिप

मैंने उसे समझ लिया। मैं सिर्फ इसके मजबूत और सप्ताह बिंदुओं को इंगित कर रहा था। हालांकि, मूल प्रश्न का उत्तर देने के लिए इसे थोड़ा और अधिक करने की आवश्यकता है क्योंकि यह एक स्ट्रिंग सीमाओं से मेल खाता है और न केवल चरित्र सीमाओं से मेल खाता है। लेकिन विचार सिर्फ एक ही है।
पॉलो मोर्गेडो

1

यदि आप युग्मित युग्मों की कई घटनाओं को संभालना चाहते हैं , तो यह RegEx के बिना आसान नहीं होगा:

Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
  • input ?? String.Empty तर्क शून्य अपवाद से बचा जाता है
  • ?=1 विकल्प रखता है और ?<=दूसरा स्थानापन्न रखता है
  • RegexOptions.Singleline सबरिंग जोड़ी के बीच न्यूलाइन की अनुमति देता है

यदि आदेश और घटाव की गणना से कोई फर्क नहीं पड़ता है, तो यह त्वरित और गंदा एक विकल्प हो सकता है:

var parts = input?.Split(new string[] { "key : ", " - " }, StringSplitOptions.None);
string result = parts?.Length >= 3 ? result[1] : input;

कम से कम यह सबसे अपवाद से बचा जाता है, मूल स्ट्रिंग को वापस करके अगर कोई भी / एकल सबस्ट्रिंग मैच नहीं करता है।


0

जैसा कि मैं हमेशा कहता हूं कि कुछ भी असंभव नहीं है:

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

Remeber को System.Text.RegularExpressions का संदर्भ जोड़ना चाहिए

आशा है कि मैंने मदद की।


0

शायद ऐसा ही कुछ

private static string Between(string text, string from, string to)
{
    return text[(text.IndexOf(from)+from.Length)..text.IndexOf(to, text.IndexOf(from))];
}

0

जब एक एकल उदाहरण के संदर्भ में प्रश्न पूछे जाते हैं तो अस्पष्टता अनिवार्य रूप से मौजूद होती है। यह सवाल कोई अपवाद नहीं है।

प्रश्न में दिए गए उदाहरण के लिए वांछित स्ट्रिंग स्पष्ट है:

super example of string key : text I want to keep - end of my string
                              ^^^^^^^^^^^^^^^^^^^

हालाँकि, यह स्ट्रिंग है, लेकिन स्ट्रिंग्स और बाउंड्री स्ट्रिंग्स का एक उदाहरण है जिसके लिए कुछ निश्चित पदार्थों की पहचान की जानी है। मैं जेनेरिक बाउंड्री स्ट्रिंग्स के साथ एक सामान्य स्ट्रिंग पर विचार करूंगा, जो निम्नानुसार है।

abc FF def PP ghi,PP jkl,FF mno PP pqr FF,stu FF vwx,PP yza
             ^^^^^^^^^^^^         ^^^^^  

PPहै पूर्ववर्ती स्ट्रिंग , FFनिम्न स्ट्रिंग है और पार्टी टोपियाँ से संकेत मिलता है जो सबस्ट्रिंग मिलान किया जा रहे हैं। (प्रश्न में दिए गए उदाहरण में key : पूर्ववर्ती स्ट्रिंग है और -निम्न स्ट्रिंग है।) मुझे लगता है कि मान लिया है PPऔर FFपहले और शब्द सीमाओं के बाद (ताकि कर रहे हैं PPAऔर FF8मेल नहीं खाते हैं)।

पार्टी की टोपियों से परिलक्षित मेरी धारणाएँ इस प्रकार हैं:

  • पहला सबस्ट्रिंग PPएक (या अधिक) FFसबस्ट्रिंग से पहले हो सकता है , जो यदि मौजूद है, तो अवहेलना की जाती है;
  • यदि सामने आने से पहले PPएक या अधिक PPएस द्वारा पीछा किया जाता FFहै, तो निम्नलिखित PPएस पूर्ववर्ती और निम्नलिखित तारों के बीच प्रतिस्थापन का हिस्सा हैं;
  • यदि मुठभेड़ से पहले PPएक या अधिक FFएस द्वारा पीछा किया जाता PPहै, तो पहले FFनिम्नलिखित PPको निम्नलिखित स्ट्रिंग माना जाता है।

ध्यान दें कि यहां बहुत से उत्तर फॉर्म के केवल तारों से संबंधित हैं

abc PP def FF ghi
      ^^^^^

या

abc PP def FF ghi PP jkl FF mno
      ^^^^^         ^^^^^

एक नियमित अभिव्यक्ति का उपयोग कर सकता है, कोड निर्माण, या ब्याज के सबस्ट्रिंग की पहचान करने के लिए दो का एक संयोजन। मैं कोई निर्णय नहीं लेता कि कौन सा दृष्टिकोण सबसे अच्छा है। मैं केवल निम्नलिखित नियमित अभिव्यक्ति प्रस्तुत करूंगा जो ब्याज के सबस्ट्रिंग से मेल खाएगी।

(?<=\bPP\b)(?:(?!\bFF\b).)*(?=\bFF\b)

अपना इंजन शुरू करो! 1

मैंने इसे PCRE (PHP) regex इंजन के साथ परीक्षण किया, लेकिन जैसा कि regex बिल्कुल विदेशी नहीं है, मुझे यकीन है कि यह .NET regex इंजन (जो बहुत मजबूत है) के साथ काम करेगा।

रेगेक्स इंजन निम्नलिखित परिचालन करता है:

(?<=          : 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

इस तकनीक को एक बार में एक वर्ण से मेल खाते हुए, पूर्ववर्ती स्ट्रिंग का अनुसरण करते हुए, जब तक कि चरित्र है Fऔर उसके बाद F(या आमतौर पर, चरित्र को निम्नलिखित स्ट्रिंग का गठन करने वाला स्ट्रिंग बनाता है), टेम्पर्ड लालची टोकन समाधान कहा जाता है ।

स्वाभाविक रूप से, अगर मैं ऊपर बताई गई धारणाओं को बदल दिया जाता है, तो रेगेक्स को संशोधित करना होगा (यदि संभव हो तो)।

1. विस्तृत विवरण के लिए कर्सर को चारों ओर ले जाएं।


0

सी # 8.0 में और ऊपर, आप सीमा ऑपरेटर का उपयोग कर सकते हैं ..के रूप में

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

देखें प्रलेखन जानकारी के लिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.