【问题标题】:how to substring from a string using c#?如何使用 c# 从字符串中提取子字符串?
【发布时间】:2011-01-19 18:39:30
【问题描述】:

字符串格式总是这样“FirstName=ABC;LastName=XZY;Username=User1;Password=1234”。

我需要唯一的 UserName 值(在本例中为“User1”)。我想使用 substring 方法(或其他方法)在最少的代码行中实现这一点。

帮助?

【问题讨论】:

  • 当一个问题有非常明确的答案时,例如这个问题,我总是很高兴看到 SO 社区提供了多少不同的解决方案。
  • 需要注意的一点:输入字符串有一个名为“Usernname”的字段。然后,您要求输入“UserName”字段。解析字符串时要注意大小写。当然,有一些方法可以解决这个问题。

标签: c# .net substring


【解决方案1】:

即使值对以不同的顺序给出,此方法也可以工作。它在分号上拆分,找到带有“用户名”的项目,然后返回等号后面的内容。

string theString = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string username = theString.Split(";").Where(s => s.Split("=")[0].Equals("Username")).ToArray()[0].Split("=")[1];

【讨论】:

  • @Aaron:很抱歉,语法可以吗。我在 .ToArray[0]..?? 附近遇到错误?
  • @user144842:您在我的示例中发现了一个错误! ToArray 后面应该有括号。我已经更新了我的答案。
  • 那将是一半 VB 和一半 C# ...... 可能完全不在他的脑海中。
  • 你的建议目前最适合我。只需在您的答案陈述中编辑最后一个 [0] 到 [1]。谢谢。
【解决方案2】:

但是不像使用拆分那么简单:

string input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string username = Regex.Match(input, "Username=(?<username>.*?)(;|$)").Groups["username"].Value;

在这种情况下,组可以按任何顺序排列。

而且,如果你想发挥创意:

var answers = from tuple in input.Split(';')
              where tuple.StartsWith("Username=")
              select tuple.Split('=')[1];

username = answers.Count() > 0 ? answers.First() : string.Empty;

有人可能会说最后一段的语义更好。

编辑:更新最后一段以处理没有所需元组的输入字符串。

【讨论】:

  • 如果源字符串是 FirstName=ABC;Username=User1;LastName=XZY;Password=1234 将失败。使用 ? 进行惰性搜索:Username=(?&lt;username&gt;.*?);
  • @Naeem Sarfraz:谢谢,你是对的。该死的贪婪。此外,我更正了用户名是字符串中最后一对的情况。现在正则表达式很复杂......
【解决方案3】:

这不是最短的……但可能是最快的之一。

string value = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
int offset = value.IndexOf("Username=") + 9;
if (offset < 9)
    throw new Exception("Username= not found in string");
int len = value.IndexOf(';', offset) - offset;
if (len < 0)
    len = value.Length - offset;
string find = value.Substring(offset, len);

...if (len &lt; 0)Username 在字符串的末尾并且不以分号结尾。如果你想忽略大小写,你可以用这个替换 int offset 行...

int offset = value.ToUpperInvariant().IndexOf("USERNAME=") + 9;

【讨论】:

  • 我知道“幻数”可以通过将“用户名=”移动到变量(如 token)并使用 token.Length 来替换。
  • 随意抱怨“例外”,我觉得没有比这更好的例子了。
【解决方案4】:

看起来像一个定界字符串,所以这可以工作:

string result = myString.Split(';')[2].Split('=')[1];

但是,如果有人更改了值对顺序,就会中断。

对此有更好的方法,如果顺序更改、参数数量不同等也不会中断 - 例如 Michael 发布的正则表达式,或许多人发布的 Linq 查询。

【讨论】:

  • 感谢您试图使其尽可能短,但我认为我们已经赢得了我最近看到的最丑陋的一段代码。 (无意冒犯!)
  • @user:我建议您使用真实姓名注册 - 我开始通过您的用户 ID 中的数字认出您。 :-)
【解决方案5】:

虽然如果没有任何变化,拆分答案是“好的”,但使用函数可能更好,因为:

  • 它让你的意图变得清晰。
  • 更容易记录。
  • 如果发生不可避免的情况,修改起来更容易。
  • 无论顺序如何都能正常工作。

(即使您只是将一行拆分放在函数中!或者至少在拆分中添加注释。)


static String GetUsername(String value)
{
    String result = "";
    String token = "Username=";

    int index = value.IndexOf(token) + token.Length;
    while (value[index] != ';')
    {
        result += value[index++];
        if (index > value.Length - 1)
            break;
    }

    return result;
}

【讨论】:

  • 我喜欢封装这个“逻辑”的建议,但让我们变得邪恶:他的样本没有以';'结尾。现在想象“用户名=”部分在最后,你的解决方案会发生什么?
  • @Benjamin - 虽然处理这种情况并不困难;我认为提出的所有解决方案都存在一些缺陷。例如,如果字符串中有两个用户名怎么办?会发生什么?这个解决方案总是选择第一个。无论如何,我认为这个微不足道的问题已经被发挥到了极致。
【解决方案6】:

为了完整起见,这里是正则表达式的做法。如果订单发生变化,这也将起作用。

// using System.Text.RegularExpressions;

string test1 = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
string test2 = "FirstName=ABC;LastName=XZY;Password=1234;Username=User1";
string test3 = "FirstName=ABC;LastName=XZY;Password=1234";

string regexPattern = @"(?<=Username=)[^;\n]*";
var userName1 = Regex.Match(test1, regexPattern).Value; // User1
var userName2 = Regex.Match(test2, regexPattern).Value; // User1
var userName3 = Regex.Match(test3, regexPattern).Value; // string.Empty

// Compiling can speed up the Regex, at the expense of longer initial Initialization
// Use when this is called often, but measure.

Regex compiledRx = new Regex(regexPattern,RegexOptions.Compiled);
var userNameCompiled1 = compiledRx.Match(test1).Value; // User1
var userNameCompiled2 = compiledRx.Match(test2).Value; // User1
var userNameCompiled3 = compiledRx.Match(test3).Value; // string.Empty

【讨论】:

    【解决方案7】:

    这是一个替代解决方案(与其他解决方案没有太大区别,但我认为它更直接),无论顺序如何都可以工作。

    var input = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
    
    Assert.AreEqual("User1", input
        .Split(';')
        .Select(item => item.Split('='))
        .Where(pair => pair[0].Equals("Username"))
        .Single()[1]);
    

    【讨论】:

    • 当字符串中没有“用户名”时失败。
    • 如果可能没有用户名,您可以在.Single() 之前添加.Select(pair =&gt; pair[1]) 并将.Single() 更改为.SingleOrDefault()。那么如果没有用户名,你就会得到 null。
    【解决方案8】:
            string t = "FirstName=ABC;LastName=XZY;Username=User1;Password=1234";
            string name = t.Split(';')[2].Split('=')[1];
    

    【讨论】:

      【解决方案9】:

      最少的代码行数并不总是最好的衡量标准,但您可以使用正则表达式做您需要的事情。

      【讨论】:

      • 多么奇怪,这可能是我第一次看到建议的正则表达式,它是一个有效的答案。 :p
      • 你没听说过 - 有些人在遇到问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。杰米·扎温斯基
      • @Tanzelax:正则表达式成为新的 JQuery?
      • 我喜欢这个答案,我应该到处告诉大家使用 C# 作为我的答案。很抱歉,但只是说您可以使用 Regex 做您需要的事情并不是一个有效的答案。提供代码示例。
      • @Stan R:我同意你至少是编程新手...示例代码有很大帮助...
      猜你喜欢
      • 2018-09-29
      • 1970-01-01
      • 2011-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-24
      • 2017-04-01
      相关资源
      最近更新 更多