簡體   English   中英

C#正則表達式拆分字符串並在拆分中包含匹配的表達式

[英]C# regex to split string and include matched expression in split

我有以下字符串:

Bacon ipsum dolor amet **kevin kielbasa** pork chop picanha chuck, 
t-bone **brisket corned beef fatback hamburger cow** sirloin shank prosciutto
shankle. T-bone pancetta ribeye **tongue** fatback drumstick frankfurter short 
ribs burgdoggen. **Tail cupim.**

我想獲得:

List<string>(){
    "Bacon ipsum dolor amet ",
    "**kevin kielbasa**",
    " pork chop picanha chuck, t-bone ",
    "**brisket corned beef fatback hamburger cow**",
    " sirloin shank prosciutto shankle. T-bone pancetta ribeye ",
    "**tongue**",
    " fatback drumstick frankfurter short ribs burgdoggen. ",
    "**Tail cupim.**"
}

處理辦法:

  1. 完全在Regex中:

首過

Regex.Split(str, @"\\*\\*.*?\\*\\*");

"Bacon ipsum dolor amet ",
" pork chop picanha chuck, t-bone ",
" sirloin shank prosciutto shankle. T-bone pancetta ribeye ",
" fatback drumstick frankfurter short ribs burgdoggen. "

拆分將刪除所有匹配項。 它將每一個視為它認為我們想要的項目之間的分隔符。 D'哦!

第二關

Regex.Matches(str, @"\\*\\*.*?\\*\\*").Cast<Match>().Select(m => m.Value).ToList();

"**kevin kielbasa**",
"**brisket corned beef fatback hamburger cow**",
"**tongue**",
"**Tail cupim.**"

好吧,那很有道理。 Regex.Matches()返回與正則表達式匹配的所有項目,因此我們丟失了之間的所有內容。

  1. 加上一些LINQ:

好的,讓我們看看是否可以將所有文本匯總到一個列表中:

Regex.Split(str, @"\\*\\*");

"Bacon ipsum dolor amet ",
"kevin kielbasa",
" pork chop picanha chuck, t-bone ",
"brisket corned beef fatback hamburger cow",
" sirloin shank prosciutto shankle. T-bone pancetta ribeye ",
"tongue",
" fatback drumstick frankfurter short ribs burgdoggen. ",
"Tail cupim."

奇怪的是,這個簡單的正則表達式使我們最接近正則表達式,但是我們不再知道列表中的哪些項被**包圍。 因為**替換每個列表項,所以我們只需要知道列表中的第一個(或第二個)項是否被**包圍。

bool firstIsMatch = "**" == new string(str.Take(2).ToArray());

然后,我們可以使用該布爾值來確定是否要在列表中每個偶數或奇數項的開頭和結尾添加“ **”。

問題:

  • 有沒有辦法用正則表達式完全做到這一點? 如果是這樣,怎么辦?
  • 盡管是“更多代碼”,但第二個選項是否在性能和/或可讀性方面是首選?

如何在Regex中使用Regex.Matches與管道Regex.Matches ,例如

(?s)\*\*.*?\*\*|.+?(?=\*\*|$)

在正則表達式風暴中查看演示

先行 或部分停止向右前**$結束。

您需要做的就是將正則表達式包裝在捕獲組中。 一旦正則表達式找到要分割的匹配項,匹配文本也將被推入結果數組中。 請參閱Regex.Split參考:

如果在Regex.Split表達式中使用了捕獲括號,則任何捕獲的文本都將包含在結果字符串array中 例如,如果在捕獲括號內的連字符上拆分字符串“ plum-pear”,則返回的數組將包含一個包含連字符的字符串元素。

以后可以使用LINQ輕松過濾出空元素:

var str  = "Bacon ipsum dolor amet **kevin kielbasa** pork chop picanha chuck, t-bone **brisket corned beef fatback hamburger cow** sirloin shank prosciutto shankle. T-bone pancetta ribeye **tongue** fatback drumstick frankfurter short ribs burgdoggen. **Tail cupim.**";
var res = Regex.Split(str, @"(\*{2}.*?\*{2})", RegexOptions.Singleline) // Split and keep  the captures
        .Where(s=>!string.IsNullOrWhiteSpace(s)); // Remove blank elements
Console.WriteLine("\"{0}\"", string.Join("\"\n\"", res));

參見C#演示

還有關於模式性能的小注釋:如果文本很大,由於惰性點匹配模式,您可能會遇到速度變慢的情況。 最好將其展開為@"\\*{2}[^*]*(?:\\*(?!\\*)[^*]*)*\\*{2}"尤其是在存在少量的“野生”,獨立星號(定界符)。

請嘗試以下操作:

var s = "Bacon ipsum dolor amet **kevin kielbasa** pork chop picanha chuck, " +
"t-bone **brisket corned beef fatback hamburger cow** sirloin shank prosciutto " +
"shankle. T-bone pancetta ribeye **tongue** fatback drumstick frankfurter short " +
"ribs burgdoggen. **Tail cupim.**";

var split = Regex.Split(s, @"(?=\*\*\S)|(?<=\S\*\*)");

foreach (var part in split)
{
    Console.WriteLine(part);
}

// == OUTPUT ==
//
// Bacon ipsum dolor amet 
// **kevin kielbasa**
//  pork chop picanha chuck, t-bone 
// **brisket corned beef fatback hamburger cow**
//  sirloin shank prosciutto shankle. T-bone pancetta ribeye 
// **tongue**
//  fatback drumstick frankfurter short ribs burgdoggen. 
// **Tail cupim.**

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM