1

この質問はこれに大きく関連していますが、グローバル変数への参照を含むメソッドを取得することに関係しています (コメントアウトされていません)。

次の正規表現とテスト文字列を使用して機能するかどうかを確認していますが、部分的にしか機能していません。

正規表現

^((?:(?:Public|Private)\s+)?(?:Function|Sub).+)[\s\S]+?(GLOBAL_VARIABLE_1)[\s\S]+?End\s+(?:Function|Sub)$

(サブマッチとしてメソッドの名前を取得できるように、このようにキャプチャ グループで正規表現の一部が必要です)。

テスト文字列

'-----------------------------------------------------------------------------------------
'
'   the code:   Header
'
'-----------------------------------------------------------------------------------------

Dim GLOBAL_VARIABLE_1
Dim GLOBAL_VARIABLE_2
Dim GLOBAL_VARIABLE_3

Public Function doThis(byVal xml)
'' Created               : dd/mm/yyyy
'' Return                : string
'' Param            : xml- an xml blob

     return = replace(xml, "><", ">" & vbLf & "<")

     GLOBAL_VARIABLE_1 = 2 + 2

     doThis = return

End Function


msgbox GLOBAL_VARIABLE_1



Public Function doThat(byVal xPath)
'' Created               : dd/mm/yyyy
'' Return                : array
' 'Param            : xPath

     return = split(mid(xPath, 2), "/")

     GLOBAL_VARIABLE_2 = 2 + 2


     doThat = return

End Function


GLOBAL_VARIABLE_2 = 2 + 2


Public Sub butDontDoThis()
'' Created               : dd/mm/yyyy
'' Return                : string
' 'Param            : obj

     For i = 0 To 5
          return = return & "bye" & " "

     Next

End Sub


GLOBAL_VARIABLE_3 = 3 + 3


Public Sub alsoDoThis(byRef obj)
'' Created               : dd/mm/yyyy
'' Return                : string
' 'Param            : obj, an xml document object

     For i = 0 To 4
          return = return & "hi" & " "

     Next

     GLOBAL_VARIABLE_1 = 1 + 1

End Sub


GLOBAL_VARIABLE_3 = 3 + 3

http://www.regexpal.com/を使用すると、グローバル変数を参照する最初のメソッドを強調表示できます。ただし、正規表現は、他の方法で期待することを行っていません。正規表現は、特定のグローバル変数への参照を持たない他のメソッドもピックアップしており、実際にグローバル変数を使用している最後のメソッドで終了します。問題は、[\s\S]+?(GLOBAL_VARIABLE_1)[\s\S]+?End\s+(?:Function|Sub)$パーツが最小限の/貪欲でない一致を行っているため、実際の一致が見つかるまで探し続けることであると判断しました。

要約すると、式は次の規則に従う必要があります。

  • メソッドの宣言の最初の端を検出したときに、現在チェックしているメソッドのスキャンを停止します。この例では、doThisalsoDoThisメソッドのみが に一致するはずGLOBAL_VARIABLE_1ですが、正規表現がどうあるべきかわかりません。
  • 正規表現は、実際にグローバル変数を使用しているメソッドのみに一致する必要があります
  • aGLOBAL_VARIABLE_1がコメント化されている場合、実際にはメソッドによって使用されていません。コメントGLOBAL_VARIABLE_1は、メソッドの肯定的な一致をトリガーするべきではありません。
4

3 に答える 3

0

説明

この正規表現は、テキストを文字列に分割し、各文字列には単一の関数またはサブルーチンが含まれます。また、目的の値の前にない関数内のコードの最初の行を探すことによって、文字列にコメントがないGLOBAL_VARIABLE_1ことを検証します。式は、次のように二重引用符で囲まれた文字列に埋め込まれている場合、通常の文字としても処理されます。'GLOBAL_VARIABLE_1'variable = "sometext ' more text" + GLOBAL_VARIABLE_1

(?:Public|Private)\s+(Function|Sub)\s+([a-z0-9]*)(?:(?!^End\s+\1\s+(?:$|\Z)).)*^(?:[^'\r\n]|"[^"\r\n]*")*GLOBAL_VARIABLE_1.*?^End\s\1\b

ここに画像の説明を入力

グループ

グループ 0 には、一致した関数/サブ全体が含まれます

  1. functionまたはsubそれに応じて含まれます
  2. 関数/サブの名前が含まれます

入力テキスト

Public Function ValidEdgeCase1(byRef obj)
  SomeVariable = "some text with an embedded ' single quote" + GLOBAL_VARIABLE_1
End Sub

Public Sub SkipEdgeCase(byRef obj)
  SomeVariable = "some text with an embedded ' single quote" ' + GLOBAL_VARIABLE_1
End Sub

Public Function FailCommented(byVal xml)
'  GLOBAL_VARIABLE_1
End Function

Public Function FAilWrongName1(byVal xPath)
  GLOBAL_VARIABLE_2
End Function

Public Sub FAilWrongName1()
  GLOBAL_VARIABLE_3
End Sub

Public Sub alsoDoThis(byRef obj)
  GLOBAL_VARIABLE_1
End Sub

Public Sub IHeartKitten(byRef obj)
  GLOBAL_VARIABLE_1
End Sub

Public Sub IHeartKitten2(byRef obj)
  GLOBAL_VARIABLE_1
End Sub

Public Function FailCommented(byVal xml)
'  GLOBAL_VARIABLE_1
End Function

サンプルコード

Imports System.Text.RegularExpressions
Module Module1
  Sub Main()
    Dim sourcestring as String = "replace with your source string"
    Dim re As Regex = New Regex("(?:Public|Private)\s+(Function|Sub)\s+([a-z0-9]*)(?:(?!^End\s+\1\s+(?:$|\Z)).)*^(?:[^'\r\n]|"[^"\r\n]*")*GLOBAL_VARIABLE_1.*?^End\s\1\b",RegexOptions.IgnoreCase OR RegexOptions.IgnorePatternWhitespace OR RegexOptions.Multiline OR RegexOptions.Singleline)
    Dim mc as MatchCollection = re.Matches(sourcestring)
    Dim mIdx as Integer = 0
    For each m as Match in mc
      For groupIdx As Integer = 0 To m.Groups.Count - 1
        Console.WriteLine("[{0}][{1}] = {2}", mIdx, re.GetGroupNames(groupIdx), m.Groups(groupIdx).Value)
      Next
      mIdx=mIdx+1
    Next
  End Sub
End Module

$matches 配列:

(
    [0] => Array
        (
            [0] => Public Function ValidEdgeCase1(byRef obj)
  SomeVariable = "some text with an embedded ' single quote" + GLOBAL_VARIABLE_1
End Sub
            [1] => Public Sub alsoDoThis(byRef obj)
  GLOBAL_VARIABLE_1
End Sub
            [2] => Public Sub IHeartKitten(byRef obj)
  GLOBAL_VARIABLE_1
End Sub
            [3] => Public Sub IHeartKitten2(byRef obj)
  GLOBAL_VARIABLE_1
End Sub
        )

    [1] => Array
        (
            [0] => Function
            [1] => Sub
            [2] => Sub
            [3] => Sub
        )

    [2] => Array
        (
            [0] => ValidEdgeCase1
            [1] => alsoDoThis
            [2] => IHeartKitten
            [3] => IHeartKitten2
        )

)
于 2013-06-16T02:08:39.717 に答える
0

犯人が見つかりました。この問題は、正規表現の強調表示された部分が原因で発生します。

((?:(?:Public|Private)\s+)?(?:Function|Sub).+)[\s\S]+?(GLOBAL_VARIABLE_1)[\s\S]+?End\s+(?:Function|Sub)

[\s\S]+?は非貪欲な一致ですが、必ずしも最短一致であるとは限りません。簡単な例:

Public Function doThis(byVal xml)
  GLOBAL_VARIABLE_1
End Function

Public Function doThat(byVal xPath)
  GLOBAL_VARIABLE_2
End Function

Public Sub butDontDoThis()
  GLOBAL_VARIABLE_3
End Sub

Public Sub alsoDoThis(byRef obj)
  GLOBAL_VARIABLE_1
End Sub

正規表現がサンプル テキストに適用されると、まず最初の関数 (太字でマークされたグループ) と一致します。

Public Function doThis(byVal xml)
  GLOBAL_VARIABLE_1
End Function

ただし、その一致の後、式の最初の部分 ( ((?:(?:Public|Private)\s+)?(?:Function|Sub).+)) は次の関数定義 ( Public Function doThat(byVal xPath)) と[\s\S]+?(GLOBAL_VARIABLE_1)一致し、次に が出現するまですべてのテキストと一致します。GLOBAL_VARIABLE_1

Public Function doThat(byVal xPath)
  GLOBAL_VARIABLE_2
End Function

Public Sub butDontDoThis()
  GLOBAL_VARIABLE_3
End Sub

Public Sub alsoDoThis(byRef obj)
  GLOBAL_VARIABLE_1
End Sub

には暗黙の「含めないEnd Functionでください」というものはありません[\s\S]+?

問題の最も簡単な解決策は、正規表現と文字列一致の組み合わせです。

Set fso = CreateObject("Scripting.FileSystemObject")
text = fso.OpenTextFile("C:\Temp\sample.txt").ReadAll

Set re = New RegExp
re.Pattern = "((?:(?:Public|Private)\s+)(Function|Sub).+)([\s\S]+?)End\s+\2"
re.Global  = True
re.IgnoreCase = True

For Each m In re.Execute(text)
  If InStr(m.SubMatches(2), "GLOBAL_VARIABLE_1") > 0 Then
    WScript.Echo m.SubMatches(0)
  End If
Next

各プロシージャ/関数の本体 ( SubMatches(2)) を抽出し、本体にInStr()が含まれているかどうかを確認しますGLOBAL_VARIABLE_1

于 2013-05-28T18:56:38.760 に答える