【问题标题】:Get string between two strings in a string获取字符串中两个字符串之间的字符串
【发布时间】:2013-06-22 16:00:52
【问题描述】:

我有一个类似的字符串:

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

我只想保留"key : "" - " 之间的字符串。我怎样才能做到这一点?我必须使用正则表达式还是可以使用其他方式?

【问题讨论】:

  • 使用substringindexof
  • 获取字符串中特定字符串之后和另一个特定字符串之前的字符串,该字符串也包含在前一个字符串所在的字符串中..
  • 您还在犹豫选择哪个答案吗?

标签: c# regex string


【解决方案1】:

或许,一个好办法就是剪掉一个子串

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

【讨论】:

    【解决方案2】:
    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);
    

    【讨论】:

      【解决方案3】:

      你可以不用正则表达式

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

      【讨论】:

      • 这会在内存中创建多个不需要的字符串。如果您关心内存,请不要使用它。
      【解决方案4】:

      这是我的方法

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

      【讨论】:

      • 这是我在修复很多事情后最终使用的那个。错误:Pos2 应该是 STR.IndexOf(LastString, Pos1) 以便从 Pos1 开始。需要进一步检查 0 Pos 值。
      【解决方案5】:

      根据您希望实现的健壮/灵活程度,这实际上可能有点棘手。这是我使用的实现:

      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 "
      

      【讨论】:

      • 我使用了你的代码,但我在 @this.IndexOf(until, startIndex + fromLength, comparison) 中发现了一个小错误,来自像“AB”这样的字符串,其中 A 来自,B 是直到,所以我从长度中删除了 +。不过我还没有深入测试过
      • @AdrianIftode:好电话。这绝对是一个错误。在 startIndex 开始搜索第二个锚点是有意义的,因为这已经超过了第一个锚点的末尾。我已经在这里修复了代码。
      • InvariantCulture 不适用于 Windows 通用应用。有什么办法可以在保留班级功能的情况下删除它? @ChaseMedallion
      • @Leon:您应该能够删除所有与文化相关的内容,.NET 将只使用当前文化进行 indexOf 操作。不过,我对 Windows 通用应用程序并不熟悉,所以我不能肯定。
      【解决方案6】:

      我认为这可行:

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

      【讨论】:

        【解决方案7】:

        正则表达式在这里是多余的。

        可以string.Split 与将string[] 用作分隔符的重载一起使用,但这是矫枉过正的。

        查看SubstringIndexOf - 前者用于获取给定字符串的部分内容、索引和长度,后者用于查找内部字符串/字符的索引。

        【讨论】:

        • 这不是矫枉过正...事实上我会说 Substring 和 IndexOf 是矫枉过正。我会说 string.Split 是正确的。正则表达式是多余的。
        • 过度杀戮或杀戮不足的意义没有实际意义,因为答案满足了发帖人的要求,即以不同于正则表达式的方式。
        • @newStackExchangeInstance:如果“key:”之前有一个“-”,它也会失败。子字符串是正确的。
        • @newStackExchangeInstance - 我相信他说的是string.Split
        【解决方案8】:

        一个有效的 LINQ 解决方案:

        string str = "super example 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
        

        【讨论】:

        • 这仅适用于单字符占位符吗?
        • 它只适用于单个字符,不是 OP 要求的,应该被否决
        【解决方案9】:
         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);
        

        【讨论】:

        • 您的代码将导致冒号返回到 newString 的开头。
        【解决方案10】:

        由于:- 是独一无二的,您可以使用:

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

        【讨论】:

        • 这个答案并没有为已经大量的现有答案添加任何有意义的东西。
        【解决方案11】:

        或者,使用正则表达式。

        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;
        

        running example

        你可以决定它是否矫枉过正。

        作为一种未得到验证的扩展方法

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

        【讨论】:

        • 当字符串包含'-'时这不起作用例如:"Equipment=1,ExternalAntenna=1-1-2,AuxPlugInUnit=2,".Between("ExternalAntenna=",", ") 返回 "1-1-2,AuxPlugInUnit=2" 下面这个答案能够处理我的情况stackoverflow.com/a/38794506/193974
        【解决方案12】:

        我使用了来自 Vijay Singh Rana 的代码 sn-p,它基本上可以完成这项工作。但如果firstString 确实已经包含lastString,则会导致问题。我想要的是从 JSON 响应中提取 access_token(没有加载 JSON 解析器)。我的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);
        }
        

        【讨论】:

        • 存在冗余。将 pos1 添加到 pos2,然后从 pos2 中减去。
        【解决方案13】:

        在 C# 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
        

        详情请见documentation

        【讨论】:

        • 我喜欢 C# 8 及以上版本的简写方法!
        【解决方案14】:

        您可以使用下面的扩展方法:

        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 : ", " - ");
        

        【讨论】:

          【解决方案15】:
          var matches = Regex.Matches(input, @"(?<=key :)(.+?)(?=-)");
          

          这仅返回“key :”和以下出现的“-”之间的值

          【讨论】:

            【解决方案16】:

            如果您正在寻找 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());
                }
            }
            

            【讨论】:

              【解决方案17】:
                private string gettxtbettwen(string txt, string first, string last)
                  {
              
                      StringBuilder sb = new StringBuilder(txt);
                      int pos1 = txt.IndexOf(first)  + first.Length;
                      int len = (txt.Length ) - pos1;
              
                      string reminder = txt.Substring(pos1, len);
              
              
                      int pos2 = reminder.IndexOf(last) - last.Length +1;
              
              
                     
              
              
              
                      return reminder.Substring(0, pos2); 
              
              
              
                  }
              

              【讨论】:

                【解决方案18】:

                当问题以单个示例的形式陈述时,不可避免地会出现模棱两可的情况。这个问题也不例外。

                对于问题中给出的示例,所需的字符串很明确:

                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 : 是前面的字符串,- 是后面的字符串。)我假设 PPFF 之前和之后是单词边界(所以 PPAFF8 不匹配)。

                我的假设,正如派对帽子所反映的那样,如下所示:

                • 第一个子字符串 PP 前面可以有一个(或多个)FF 子字符串,如果存在,则忽略它们;
                • 如果在遇到FF 之前PP 后跟一个或多个PPs,则后面的PPs 是前后字符串之间的子字符串的一部分;
                • 如果在遇到PP 之前PP 后跟一个或多个FFs,则将PP 之后的第一个FF 视为以下字符串。

                请注意,这里的许多答案只处理表单的字符串

                abc PP def FF ghi
                      ^^^^^
                

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

                可以使用正则表达式、代码结构或两者的组合来识别感兴趣的子字符串。我不判断哪种方法最好。我将只提供以下将匹配感兴趣的子字符串的正则表达式。

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

                Start your engine!1

                我使用 PCRE (PHP) 正则表达式引擎对此进行了测试,但由于正则表达式一点也不陌生,我确信它可以与 .NET 正则表达式引擎(非常强大)一起使用。

                正则表达式引擎执行以下操作:

                (?<=          : 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(或更一般地说,字符是构成后面字符串的字符串),被称为Tempered Greedy Token Solution

                如果我上面提出的假设发生变化,自然就必须修改正则表达式(如果可能的话)。

                1.移动光标查看详细说明。

                【讨论】:

                  【解决方案19】:

                  如果你想处理多次出现的子字符串对,没有 RegEx 就不容易了:

                  Regex.Matches(input ?? String.Empty, "(?=key : )(.*)(?<= - )", RegexOptions.Singleline);
                  
                  • input ?? String.Empty 避免参数空异常
                  • ?= 保留第一个子字符串,?&lt;= 保留第二个子字符串
                  • RegexOptions.Singleline 允许子字符串对之间换行

                  如果子字符串的顺序和出现次数无关紧要,那么这个快速而肮脏的选项可能是一种选择:

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

                  至少它避免了大多数异常,如果没有/单个子字符串匹配,则返回原始字符串。

                  【讨论】:

                    【解决方案20】:

                    您已经有了一些好的答案,但我意识到我提供的代码远不是最有效和最干净的。但是,我认为它可能对教育目的有用。我们可以整天使用预先构建的类和库。但是如果不了解内部运作,我们只是在模仿和重复,永远不会学到任何东西。此代码有效,并且比其他一些代码更基本或“处女”:

                    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'' 来提取它,那将是完美的。
                    • 我同意。正如我所提到的,它远非有效。我不推荐使用这个算法。这只是“简单化”,这样他就可以理解较低级别的字符串。如果他只是想完成工作,他已经有了可以实现这一目标的答案。
                    • 我明白这一点。我只是指出它的强项和周点。虽然,要回答原始问题,它需要更多,因为它需要匹配字符串边界而不仅仅是字符边界。但想法是一样的。
                    【解决方案21】:

                    正如我常说的,没有什么是不可能的:

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

                    请记住应该添加 System.Text.RegularExpressions 的引用

                    希望我有所帮助。

                    【讨论】:

                      【解决方案22】:

                      可能是这样的

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

                      【讨论】:

                        【解决方案23】:
                        getStringBetween(startStr, endStr, fullStr) {
                            string startIndex = fullStr.indexOf(startStr);
                            string endIndex= fullStr.indexOf(endStr);
                            return fullStr.substring(startIndex + startStr.length, endIndex);
                        }
                        

                        【讨论】:

                        • @KiranAmadipudi。欢迎来到 StackOverflow。请提供一些解释,为什么您认为您提出的解决方案可能对 OP 有所帮助。
                        【解决方案24】:

                        在这里;

                         /// <summary>
                            /// 
                            /// </summary>
                            /// <param name="line"></param>
                            /// <param name="begin_tag"></param>
                            /// <param name="end_tag"></param>
                            /// <param name="lastIndexOfEndTag"></param>
                            /// <returns></returns>
                            private string getBetween(string line, string begin_tag, string end_tag, bool lastIndexOfEndTag = false, bool returnNullIfTagsNotExists = false)
                            {
                                if (!string.IsNullOrEmpty(line) && !string.IsNullOrEmpty(begin_tag) && !string.IsNullOrEmpty(end_tag))
                                {
                                    //          1         2         3         4         5         6         7
                                    //0123456789012345678901234567890123456789012345678901234567890123456789012
                                    //StdErrorData:   Duration: 01:59:54.88, start: 0.000000, bitrate: 557 kb/s
                                    int startIndex = line.IndexOf(begin_tag);
                                    if (startIndex >= 0)
                                    {
                                        startIndex += begin_tag.Length;
                                    }
                                    else
                                    {
                                        if (returnNullIfTagsNotExists)
                                        {
                                            return null;
                                        }
                                        else
                                        {
                                            startIndex = 0;
                                        }
                                    }
                                    int endIndex = lastIndexOfEndTag ?
                                        line.LastIndexOf(end_tag, startIndex)
                                        : line.IndexOf(end_tag, startIndex);
                                    if (endIndex > startIndex)
                                    {
                                        return line.Substring(startIndex, endIndex - startIndex);
                                    }
                                    else
                                    {
                                        if (returnNullIfTagsNotExists)
                                        {
                                            return null;
                                        }
                                        else
                                        {
                                            return line.Substring(startIndex);
                                        }
                                    }
                                }
                                return null;
                            }
                        

                        测试;

                        string r = getBetween("StdErrorData:   Duration: 01:59:54.88, start: 0.000000, bitrate: 557 kb/s", "Duration:", ",");
                        Console.WriteLine($"<{r}>");
                        //< 01:59:54.88>
                        

                        【讨论】:

                          【解决方案25】:

                          这是扩展方法,以防任何人也有兴趣保留开始和结束文本。

                          public static string SubstringBetween(this string text, string start, string end, bool keepStartEndText = false)
                              {
                                  var startIndex = text.IndexOf(start);
                                  var endIndex = text.LastIndexOf(end);
                          
                                  if (keepStartEndText)
                                      return text.Substring(startIndex, (endIndex + end.Length) - startIndex);
                                  else
                                      return text.Substring(startIndex + start.Length, endIndex - (startIndex + start.Length));
                              }
                          

                          【讨论】:

                            【解决方案26】:
                                public static string ExtractBetweenTwoStrings(string FullText, string StartString, string EndString, bool IncludeStartString, bool IncludeEndString)
                                {
                                    try { int Pos1 = FullText.IndexOf(StartString) + StartString.Length; int Pos2 = FullText.IndexOf(EndString, Pos1); return ((IncludeStartString) ? StartString : "") 
                                            + FullText.Substring(Pos1, Pos2 - Pos1) + ((IncludeEndString) ? EndString : ""); } catch (Exception ex) { return ex.ToString(); } //return ""; }
                                }
                            

                            感谢:https://www.c-sharpcorner.com/blogs/how-to-extract-a-string-lies-between-two-strings-in-c-sharpnet1

                            【讨论】:

                              【解决方案27】:

                              对于字符串之间的获取字符串,我使用这种方法:

                              public static class Extension
                              {
                                  /// <summary>
                                  /// Gets currently string between
                                  /// </summary>
                                  /// <param name="word">Currently string</param>
                                  /// <param name="start">String left</param>
                                  /// <param name="end">String right</param>
                                  /// <returns>String between start and end</returns>
                                  /// <example>The string "value (4815162342)" use Between("(",")") generates in method: "4815162342"</example>
                                  public static string Between(this string word, string start, string end)
                                  {
                                      if (start.Equals(end))
                                          throw new ArgumentException("Start string can't equals a end string.");
                              
                                      int startIndex = word.LastIndexOf(start) + 1;
                                      int endIndex = word.LastIndexOf(end) - 1 - word.LastIndexOf(start);
                              
                                      return word.Substring(startIndex, endIndex);
                                  }
                              }
                              

                              【讨论】:

                                猜你喜欢
                                • 2012-12-28
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2022-12-13
                                • 1970-01-01
                                • 2013-09-12
                                相关资源
                                最近更新 更多