簡體   English   中英

正則表達式環顧

[英]regular expression lookaround

我認為僅使用正則表達式是不可能的,但是我不是專家,所以我認為值得一問。

我正在嘗試使用.NET正則表達式進行大量搜索並替換C#代碼。 我想做的是找到一行代碼,其中在DateTime類型的變量上調用特定函數。 例如:

axRecord.set_Field("CreatedDate", m_createdDate);

而且我知道在代碼文件的前面是DateTime變量b / c是這樣的:

DateTime m_createdDate;

但似乎我不能像下面這樣在否定性后面使用命名組:

(?<=DateTime \k<1>.+?)axRecord.set_[^ ]+ (?<1>[^ )]+)

如果我嘗試匹配變量聲明和函數調用之間的所有文本,如下所示:

DateTime (?<1>[^;]+).+?axRecord.set.+?\k<1>

它將找到第一個匹配項-首先基於聲明的第一個變量-但隨后找不到任何其他匹配項,因為代碼的布局如下:

DateTime m_First;
DateTime m_Second;
...
axRecord.set_Field("something", m_First);
axRecord.set_Field("somethingElse", m_Second);

第一個匹配項包含第二個變量聲明。

是否有一種僅使用正則表達式執行此操作的好方法,還是我必須在邏輯上求助於腳本?

看看我對這個問題的回答從C#文件中獲取方法內容

它提供了指向頁面的鏈接,這些頁面顯示了如何使用內置的.net語言解析器來簡單,可靠地執行此操作(即,不是通過詢問“我正在尋找的用法”,而是通過使用VS代碼正確地解析了代碼)解析工具)。

我知道這不是RegEx的答案,但我不認為RegEx是答案。

使用單個正則表達式很難做到這一點。 但是,如果您考慮對狀態稍有處理的行,則可以這樣做。

注意:我無法在axRecord行上確切告訴您要匹配的內容,因此您可能需要適當地調整該正則表達式。

void Process(List<string> lines) {
  var comp = StringComparer.Ordinal;
  var map = new Hashset<string>comp);
  var declRegex = new Regex("^\s(?<type>\w+)\s*(?<name>m_\w+)\s*";);
  var toReplaceRegex = new Regex("^\s*axRecord.set_(?<toReplace>.*(?<name>m_\w+).*)");

  for( var i = 0; i < lines.Length; i++) {
    var line = lines[i];
    var match = declRegex.Match(line);
    if ( match.Success ) {
      if ( comp.Equals(match.Groups["type"], "DateTime") ) {
        map.Add(comp.Groups["name"]);
      } else {
        map.Remove(comp.Groups["name"]);
      }
      continue;
    }

    match = toReplaceRegex.Match(line);
    if ( match.Success && map.Contains(match.Groups["name"]) ) {
      // Add your replace logic here
    }
}

這不能使用正則表達式來完成。 一方面,C#的語法不規則。 但更重要的是,您正在談論分析在詞匯上不相關的表達式。 對於這種事情,您將需要完整的語義分析。 這意味着詞法分析器,解析器,名稱綁定以及最后的類型檢查器。 獲得帶注釋的AST之后,您可以查找所需的字段,然后直接讀取類型。

我猜這比您想做的工作要多得多,因為它大約是成熟的C#編譯器的一半。

真奇怪 我設法建立了一個確實找到它的正則表達式,但它僅與第一個匹配。

(?<=private datetime (?<1>\b\w+\b).+?)set_field[^;]+?\k<1>

因此,如果我不能在后備條件中使用命名組,則至少可以在后備條件中建立命名組,並在比賽中使用它。 但是然后看起來像當它僅與函數調用(這就是我想要的)匹配時,插入號位置已移動到該行,因此它找不到任何新匹配項,因為它已傳遞了它們的聲明。 也許我不明白引擎是如何工作的。

我猜我正在尋找的是一個正則表達式選項,它告訴它在匹配項中查找更多匹配項。 想到這一點,似乎也需要基本的html regex解析。 您找到一個標簽,然后將其作為結束標簽,並且整個頁面都包含在該匹配項中,因此除非您遞歸地將模式應用於每個匹配項,否則您將找不到其他任何標簽。

任何人對此一無所知,或者我在瘋嗎?

嘗試這個:

@"(?s)set_Field\(""[^""]*"",\s*(?<vname>\w+)(?<=\bDateTime\s+\k<vname>\b.+)"

通過先進行后向查找,您將強制正則表達式按特定順序搜索方法調用:變量聲明的順序。 您想要做的是先匹配一個看起來很可能的方法調用,然后使用后向驗證變量的類型。

我只是對與方法調用匹配的部分進行了粗略的猜測。 就像其他人所說的那樣,無論您使用什么正則表達式都必須根據您的代碼量身定制; 沒有通用的解決方案。

暫無
暫無

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

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