簡體   English   中英

正則表達式遵循模式,大括號之間除外

[英]Regex to follow pattern except between braces

我很難找出一個干凈的正則表達式(在 Javascript 實現中),它將盡可能多地捕獲一條線,因為它可以遵循一個模式,但是大括號內的任何東西都不需要遵循這個模式。 我不確定最好的解釋方式,除了舉例:

例如:假設模式是,行必須以 0 開頭,在任何地方以 0 結尾,但只允許其間有 1、2 或 3 的序列,所以我使用^(0[123]+0) 這應該匹配字符串的第一部分:


    0213123123130
    012312312312303123123
    01231230123123031230
    etc.

但我希望能夠在大括號之間插入{gibberish}並讓正則表達式允許它破壞模式。 即,忽略花括號的模式和里面的所有內容,但仍然捕獲包括{gibberish}在內的完整字符串。 所以這將以粗體捕獲所有內容:


    01232231{whatever 3 gArBaGe? I want.}121{foo}2310312{bar}3120123

即使模式正確,大括號內的 0 也不會過早結束捕獲。


    01213123123123{21310030123012301}31231230123

編輯:現在,我知道我可以做類似^0[123]*?(?:{.*})*?[123]*?0的事情嗎? 但這只有在有一組大括號時才有效,現在我必須復制我的[123]模式。 隨着[123]模式變得越來越復雜,讓它在正則表達式中出現不止一次開始變得非常難以理解。 最好的正則表達式技巧之類的東西似乎很有希望,但我不知道如何在這里應用它。 使用瘋狂的環視似乎是現在唯一的方法,但我希望有一種更清潔的方法。

由於您已指定要包括垃圾在內的整個匹配項,因此您可以使用^0([123]+(?:{[^}]*}[123]*)*)0並使用 $1 來獲取部分在 0 之間,或 $0 以獲得匹配的所有內容。

https://regex101.com/r/iFSabs/3

以下是正則表達式如何工作的概要:

  • ^將匹配錨定在行首
  • 0匹配文字零字符
  • ([123]+(?:{[^}]*}[123]*)*)是一個捕獲組,它捕獲其中的所有內容。
    • [123]+匹配123的一個或多個實例
    • (?:{[^}]*}[123]*)*是一個非捕獲組。 即它將成為比賽的一部分,但不會有 $# 用於替換或比賽。
      • {[^}]*}匹配文字{后跟任意數量的非}字符后跟 }
      • [123]*匹配123的零個或多個實例
      • 那么這整個非捕獲組可以匹配0次或多次。

此正則表達式背后的過程稱為展開循環。 http://www.softec.lu/site/RegularExpressions/UnrollingTheLoop給出了很好的描述。 (有一些錯字修復)

展開循環技術是基於這樣一個假設,即在大多數情況下,您會 [知道] 在 [重復] 交替中,哪種情況應該是最常見的,哪種情況是例外的。 我們將第一個稱為正常情況,將第二個稱為特殊情況。 展開循環技術的一般語法可以寫成:

正常*(特殊正常*)*

這可能意味着類似,匹配正常情況,如果你找到一個特殊情況,匹配它而不是再次匹配正常情況。 [你會]注意到這個語法的一部分可能[潛在地]導致超線性匹配。

使用 Regex#test 和 Regex#match 的示例:

 const strings = [ '0213123123130', '012312312312303123123', '01231230123123031230', '01213123123123{21310030123012301}31231230123', '01212121{hello 0}121312', '012321212211231{whatever 3 gArBaGe? I want.}1212313123120123', '012321212211231{whatever 3 gArBaGe? I want.}121231{extra garbage}3123120123', ]; const regex = /^0([123]+(?:{[^}]*}[123]*)*)0/ console.log('tests') console.log(strings.map(string => `'${string}': ${regex.test(string)}`)) console.log('matches'); let matches = strings.map((string) => regex.exec(string)).map((match) => (match? match[1]: undefined)); console.log(matches);

Robo Robok 的答案是 go 如果您只想保留非支撐部分,盡管使用稍微不同的正則表達式( {[^}]*} )以獲得更高的性能。

反過來呢? 檢查刪除了卷曲標簽的字符串:

const string = '012321212211231{whatever 3 gArBaGe? I want.}1212313123120123{foo}123';
const stringWithoutTags = string.replace(/\{.*?\}/g, '');

const result = /^(0[123]+0)/.test(stringWithoutTags);

您說您需要捕獲所有內容,包括亂碼,所以我認為像這樣的簡單模式應該可以工作:

^(0(?:[123]|{.+?})+0)

這允許以 0 開頭的字符串,然后是任何模式字符(1、2 或 3){ gibberish }部分之一,並允許重復處理多個亂碼部分,最后它必須以一個 0。

https://regex101.com/r/K4teGY/2

你可能會使用

^0[123]*(?:{[^{}]*}[123]*)*0
  • ^字符串開頭
  • 0匹配一個零
  • [123]*匹配 0+ 次 1、2 或 3
  • (?:非捕獲組
    • {[^{}]*}[123]*匹配從開始到結束}后跟 0+ 1、2 或 3
  • )*關閉組並重復 0+ 次
  • 0匹配一個零

正則表達式演示

暫無
暫無

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

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