C# 这个字符串操作I';我在尝试吗?

C# 这个字符串操作I';我在尝试吗?,c#,string,C#,String,我有以下格式的字符串: “[someTitle1]第一名$$[someTitle2]第二名$$[someTitle3]第三名$[someTitle4]第四名$[someTitle5]第五名$$[someTitle6]第六名” 我想从中接收以下字符串: “thirdName.fourthName.fifthName.sixthName”(输入字符串的长度可能不同,但我希望始终获得最后四个元素(保证至少有4个) 我可以在一行内(或在其附近)执行此操作吗?Regex以捕获所有以']'开头的单词。然后从

我有以下格式的字符串: “[someTitle1]第一名$$[someTitle2]第二名$$[someTitle3]第三名$[someTitle4]第四名$[someTitle5]第五名$$[someTitle6]第六名”

我想从中接收以下字符串:
“thirdName.fourthName.fifthName.sixthName”
(输入字符串的长度可能不同,但我希望始终获得最后四个元素(保证至少有4个)


我可以在一行内(或在其附近)执行此操作吗?

Regex以捕获所有以']'开头的单词。然后从每个匹配中提取“值”。颠倒顺序,取前四个,然后再颠倒。然后用“.”连接它

var last4 = 
    new Regex(@"(?<=\])\w+")
    .Matches(str)
    .Cast<Match>()
    .Select(match => match.Value)
    .Reverse()
    .Take(4)
    .Reverse()
    .Aggregate((a,b) => a + '.' + b);
var last4=

新正则表达式(@“(?假设您始终至少有4对标题/名称对,您可以先在
$$
上进行拆分,然后使用skip获取最后4对,然后在
]
上进行拆分,以仅获取名称部分。请注意,您可能需要添加检查,以确保
的长度至少为4,并且在执行plit on
]
如果可能有与您的格式不匹配的输入,它实际上会产生两个结果。这还假设您的标题或名称中没有双问号或方括号

var pairs = str.Split(new[] { "$$" });
var lastFour = pairs.Skip(pairs.Length -4)
    .Select(x => x.Split(']')[1]);
var result = string.Join(".", lastFour);
使用新的C#(仅限C#8.0、.NET Core),这将成为一个单行程序:

string result = String.Join('.', Regex.Split(input, @"(^|\$\$)\[\w+]")[^4..]);
请注意,此正则表达式使用
$$[someTitle]
部分作为分隔符(或仅在开头使用
[someTitle]

(^ |\$\$)
匹配行首(
^
)或(
\
)双精度
$
\
转义,因为
$
在正则表达式中具有特殊含义“行尾”。
[
也被转义,因为它表示字符集的开头。
\w
表示字母数字字符。
+
表示其中至少有一个字符,但可能有很多。如果标题中可能出现字母和数字以外的字符,则将
\w+
替换为
+?
(导致
(^ | \$\$)\[.+?]
)其中
代表任何字符。
+?
表示至少一个字符,但尽可能少,否则
+
将消耗结尾
]
直到最后一个
]

使用.NET标准2.1/.NET Core 2.0,您可以使用新的
TakeLast
LINQ扩展方法:

string result = String.Join(".", Regex.Split(input, @"(^|\$\$)\[\w+]").TakeLast(4));
对于其他版本的C#:


太多人开始使用
Regex
来解决每个问题。然而,解析类似的东西正是Regex擅长的

首先创建一个模式:

private const string NameTitlePattern = @"\[(?<title>\w+)](?<name>\w+)[(\$\$)$]";
private static readonly Regex _nameTitleRegex = new Regex(NameTitlePattern);


$$
拆分,然后按
]
拆分?@GSerg按
$$$
拆分是显而易见的,我的主要问题是去掉标题和它们的括号。你不必这样做。按
]
拆分,你会在第二个元素中得到干净的名称,在第一个元素中得到垃圾。正则表达式应该真正搜索双问号作为匹配结束,因为名称可能包含非单词字符,甚至可能包含单个问号。您不需要调用
ToArray
,因为
字符串太多。Join
接受
IEnumerable
是,但仅从.NET 5.0开始这是什么意思?string.Join接受了IEnumerable for…比如ever@pinkfloydx33,@juharr:看来你们都是对的。它是从.NET 4.0开始存在的,以
字符串作为分隔符,从.NET Core 2.0/.NET Standard 2.1开始,以
字符作为分隔符。我必须展开“应用于”部分才能看到它。
private const string NameTitlePattern = @"\[(?<title>\w+)](?<name>\w+)[(\$\$)$]";
private static readonly Regex _nameTitleRegex = new Regex(NameTitlePattern);
private const string NameTitleStuff =
    @"[someTitle1]firstName$$[someTitle2]secondName$$[someTitle3]thirdName$$[someTitle4]fourthName$$[someTitle5]fifthName$$[someTitle6]sixthName";
var result = new List<KeyValuePair<string, string>>();
var matches = _nameTitleRegex.Matches(NameTitleStuff);
foreach (var match in matches.Cast<Match>())
{
    var groups = match.Groups;
    result.Add(new KeyValuePair<string, string>(groups["title"].ToString(), groups["name"].ToString()));
}
var result = matches
    .Cast<Match>()
    .Select(match => match.Groups)
    .Select(groups => new KeyValuePair<string, string>(
        groups["title"].ToString(),
        groups["name"].ToString()))
    .ToList();