C# 从字符串中获取特定部分

C# 从字符串中获取特定部分,c#,regex,C#,Regex,我试图从字符串中获取特定部分。我必须得到以@开头的部分,它只包含拉丁字母表中的字母 我想我必须创建一个正则表达式模式,但我不知道如何创建 string test = "PQ@Alderaa1:30000!A!->20000"; var planet = "Alderaa"; //what I want to get string test2 = "@Cantonica:3000!D!->4000NM"; var planet2 = "Cantonica"; 还有一些其他的部分,我必

我试图从字符串中获取特定部分。我必须得到以@开头的部分,它只包含拉丁字母表中的字母

我想我必须创建一个正则表达式模式,但我不知道如何创建

string test = "PQ@Alderaa1:30000!A!->20000";
var planet = "Alderaa"; //what I want to get
string test2 = "@Cantonica:3000!D!->4000NM";
var planet2 = "Cantonica";

还有一些其他的部分,我必须得到,但我会尽量让他们自己。(在“:”之后开始,是一个整数;可能是“A”(攻击)或“D”(销毁),必须用“!”(感叹号)包围;在“->”之后开始,应该是一个整数)

您可以使用这个正则表达式,它使用正向查找来确保匹配的文本前面有
@
并且使用
捕获一个或多个字母表[a-zA-Z]+
并使用积极的前瞻性,以确保它后面紧跟一些可选文本、冒号、一个或多个数字,然后紧跟
,然后是
a
D
,然后是

(?<=@)[a-zA-Z]+(?=[^:]*:\d+![AD]!)

您可以使用捕获组获取单独的部分:

@([a-zA-Z]+)[^:]*:(\d+)!([AD])!->(\d+)
这将符合:

  • @([a-zA-Z]+)
    匹配
    @
    并在第1组中捕获1+次a-zA-Z
  • [^::*:
    使用一个否定的数字匹配0+次非a
    ,然后匹配a
    (如果下面的数字只能是可选数字,您也可以匹配0+次数字
    [0-9]*
  • (\d+)在第2组中捕获1+个数字
  • !([AD])!
    Match!,在第3组和A或D组中捕获,然后匹配
  • ->(\d+)
    匹配
    ->
    并捕获第4组1+位数字

|

您已经有了一个很好的答案,但我想添加一个新答案来显示命名的捕获组

你可以为你的行星创建一个类,比如

class Planet
{
  public string Name;
  public int Value1; // name is not cleat from context
  public string Category; // as above: rename it
  public string Value2; // same problem
}
现在,您可以将正则表达式与命名组一起使用

@(?<name>[a-z]+)[^:]*:(?<value1>\d+)!(?<category>[^!]+)!->(?<value2>[\da-z]+)
@(?[a-z]+)[^::*:(?\d+)(?[^!]+)!->(?[\da-z]+)

用法:

var input = new[]
{
    "PQ@Alderaa1:30000!A!->20000",
    "@Cantonica:3000!D!->4000NM",
};

var regex = new Regex("@(?<name>[a-z]+)[^:]*:(?<value1>\\d+)!(?<category>[^!]+)!->(?<value2>[\\da-z]+)",
    RegexOptions.IgnoreCase | RegexOptions.Compiled);

var planets = input
    .Select(p => regex.Match(p))
    .Select(m => new Planet
    {
        Name = m.Groups["name"].Value, // here and further we can access to part of input string by name
        Value1 = int.Parse(m.Groups["value1"].Value),
        Category = m.Groups["category"].Value,
        Value2 = m.Groups["value2"].Value
    })
    .ToList();
var输入=新[]
{
"PQ@Alderaa1:30000!A!->20000“,
“@Cantonica:3000!D!->4000NM”,
};
var regex=new regex(“@(?[a-z]+)[^::*:(?\\d+)(?[^!]+)!->(?[\\da-z]+)”,
RegexOptions.IgnoreCase | RegexOptions.Compiled);
变量=输入
.Select(p=>regex.Match(p))
.选择(m=>new Planet
{
Name=m.Groups[“Name”].Value,//我们可以通过名称访问输入字符串的一部分
Value1=int.Parse(m.Groups[“Value1”].Value),
类别=m.组[“类别”]值,
Value2=m.Groups[“Value2”].值
})
.ToList();

wauw这很有趣,我从来没有真正研究过正则表达式模式,我只是简单地进行了分解等等。这是如何工作的?这会返回一个带有结果的数组吗?@Livo获取捕获组的一种方法是这样的,使用“谢谢”,这对我非常有帮助!@Thefourthbird,谢谢你的回答!我正在测试正则表达式,但是为什么它不匹配整个单词,只匹配“Cantonic”。@啊,我明白了,我已经更新了它
@([a-zA-Z]+)[^::*:(\d+)([AD])!->(\d+)
可能是个愚蠢的问题,但是“p”在代码段中做了什么,它在哪里声明,或者像for循环,在内部声明?@Livo
p
是一个lambda参数,它声明为“inline”。您可以重命名它以实现
planet=>regex.Match(planet)
它仍然可以工作。与
m
参数相同哦,所以你把每个输入都放在一个p中,这似乎是每个的某种形式,然后用p为每个选择一个新的m,并定义行星,其中p只是正则表达式匹配的地方,m是值:D。谢谢!我发现这是构建和测试正则表达式的一个很好的资源。
@(?<name>[a-z]+)[^:]*:(?<value1>\d+)!(?<category>[^!]+)!->(?<value2>[\da-z]+)
var input = new[]
{
    "PQ@Alderaa1:30000!A!->20000",
    "@Cantonica:3000!D!->4000NM",
};

var regex = new Regex("@(?<name>[a-z]+)[^:]*:(?<value1>\\d+)!(?<category>[^!]+)!->(?<value2>[\\da-z]+)",
    RegexOptions.IgnoreCase | RegexOptions.Compiled);

var planets = input
    .Select(p => regex.Match(p))
    .Select(m => new Planet
    {
        Name = m.Groups["name"].Value, // here and further we can access to part of input string by name
        Value1 = int.Parse(m.Groups["value1"].Value),
        Category = m.Groups["category"].Value,
        Value2 = m.Groups["value2"].Value
    })
    .ToList();