正则表达式匹配文件夹名称本地(相对和绝对)和LAN

时间:2017-06-23 06:27:18

标签: regex vb.net

如果Windows文件夹名称可能有效,我需要检查。该文件夹尚未存在。它可以是绝对路径,相对路径,也可以位于网络中的另一台机器上(通过UNC寻址)。

以下是有效的地点:

[[X:]\]                     'Including an empty string.
\\server name\              'Including \\123.123.123.123\

请注意,Windows确实接受/而不是\(要验证,请在文件资源管理器中输入C:/Users)。

该位置后面可以跟一个深层路径,并且必须以包含或不包含结尾斜杠的路径名终止:

[folder name\]*folder name[\]

任何字符/\:*?<>"|都不会出现在服务器名称或文件夹名称中。

这可以通过将提供的文本与正则表达式进行匹配来完成。因此我创造了一个这样的:

^                             'At the beginning of the string must appear 
    (                         'either
        \\{2}                 '2 backslashes
        [^/\\\:\*\?\<\>\|]+   'followed by a server name
        (\\|/)                'and a slash,
    |                         'or
        (                     'a sequence of
            (\.{2})           '2 dots
            (\\|/)            'followed by a slash
        )+                    'which may occur at least one time
    |                         'or
        [A-Za-z]              'a drive letter
        \:                    'followed by a colon
        (\\|/)                'and a slash
    |                         'or
        (\\|/)                'simply a slash
    )?                        'or nothing at all;
(                             'followed by a sequence of
    [^/\\\:\*\?\<\>\|]+       'a folder name
    (\\|/)                    'followed by a slash
)*                            'which may occur multiple times
[^/\\\:\*\?\<\>\|]+           'The last folder needs no final slash
(\\|/)?                       'but may have one.

调用以下函数:

Private Function IsDirValid(sFile As String) As Boolean
    Dim sPattern As String = "^[^/\\\:\*\?\<\>\|]+(\\|/)" &
                                "|((\.{2})(\\|/))+" &
                                "|[A-Za-z]\:(\\|/)" &
                                "|(\\|/)" &
                             ")?" &
                             "([^/\\\:\*\?\<\>\|]+(\\|/))*" &
                             "[^/\\\:\*\?\<\>\|]+(\\|/)?"
    Dim oMatch As Match = Regex.Match(sFile, sPattern)

    'Debug.Print("""" & sFile & """ returns """ & oMatch.Value & """")

    Return (sFile = oMatch.Value)
End Function

这似乎工作不算太糟糕。这些表达式都被认为是有效的:

path name[/]
path name/path name/path name[/]
/path name[/]
/path name/path name/path name[/]
../../path name[/]
../../path name/path name/path name[/]
c:/path name[/]
c:/path name/path name/path name/file name[/]
\\server name/path name[/]
\\server name\path name\path name\path name[/]

(我有没有想念?)

我唯一的问题是,每个path name确实允许前导和尾随空格。 路径名中不允许这样做。但是,允许使用“in-name”空格。

当然,我可以替换3次出现的

[^/\\\:\*\?\<\>\|]+

通过

[^/\\\:\*\?\<\>\|\ ][^/\\\:\*\?\<\>\|]*[^/\\\:\*\?\<\>\|\ ]

这将解决空白问题(测试),但引入另一个:名称现在至少需要2个字符(当然是不可接受的)。而且它变得丑陋。

唉,在regex quick reference guide我无法为我的问题找到合适的量词。

那么:有更简洁的方法吗?

1 个答案:

答案 0 :(得分:0)

一种可能的解决方案,虽然不是太漂亮,但却是

的替代品
[^/\\\:\*\?\<\>\|]

使用此构造:

(([^/\\\:\*\?\<\>\|\ ][^/\\\:\*\?\<\>\|]*[^/\\\:\*\?\<\>\|\ ])|[^/\\\:\*\?\<\>\|\ ])

其中包括:

(1)因为第一个字符允许不允许的字符但不允许空格,然后允许多个不允许的字符(也是空格),并且最后一个字符允许不允许的字符但不允许空格;

(2)因为只有字符允许不允许的字符,但不允许空格。

OP中的正则表达式进行了相当多的修改,可以从下面的代码片段中推断出来。如果需要,我可以更详细地写下来。

要测试你可以使用这个函数(在生产代码中你需要注意只构造一次正则表达式):

'Test if the provided folder name is potentially valid (it does not need to
'exist already).
Private Function IsDirValid(sDir As String) As Boolean
    'There are two sets of disallowed characters in server, share and folder 
    'names. Leading And trailing whitespace is not allowed, whitespace within
    'a name is ok. \"" is escaping a single doublequote mark for syntactical
    'reasons in VB. SLASH is defined just for readability. {DRIVE} and 
    '{LOCALDIR} are used twice each, so they are encoded as well.
    Const ALLOWBLANKDOT As String = "[^\x00-\x1F/\\\:\*\?\<\>\""\|]"
    Const FORBIDBLANKDOT As String = "[^\x00-\x1F/\\\:\*\?\<\>\""\|\ \.]"
    Const SLASH As String = "(\\|/)"
    Const DRIVE As String = "((\\{2}\?\\)?[A-Za-z]\:)"
    Const LOCALDIR As String = "({NAME}|\.{1,2}({SLASH}(\.{2}))*)"

    'Qualify zero-length strings as False. Pathes may be only 260 characters
    'long, including a terminating NUL character and 12 characters to
    'specify the short 8.3 DOS name. Because this limit includes also a file
    'name not evaluated here, at least two characters (for the slash and at
    'least one file name character) are subtracted also, for a maximum 
    'path length of 245 characters.
    If sDir.Length = 0 OrElse sDir.Length > 245 Then Return False

    'The text identifying a single path level is lengthy and appears multiple
    'times. For clarity, it is presented with {NAME} in a first step, which 
    'is substituted afterwards by an abstraction of which characters can be 
    'used depending on character position. Eventually, the abstractions are 
    'substitued by the proper regex ensuring that names can contain in-name 
    'spaces and dots, but neither leading or trailing spaces nor dots. 
    '{SLASH} is just used for enhanced readability.
    Dim sPattern As String = "^(\\{2}(\?\\UNC\\)?{NAME}{SLASH}{NAME}" &
                                 "|(({DRIVE}{SLASH}?{LOCALDIR}?)" &
                                  "|({DRIVE}?{SLASH}?{LOCALDIR}))" &
                                 "|{NAME}" &
                             ")?" &
                             "({SLASH}{NAME})*" &
                             "{SLASH}?"
    sPattern = Replace(sPattern, "{DRIVE}", DRIVE)
    sPattern = Replace(sPattern, "{LOCALDIR}", LOCALDIR)
    sPattern = Replace(sPattern, "{NAME}",
        "(({FORBIDBLANKDOT}{ALLOWBLANKDOT}*{FORBIDBLANKDOT})" &
         "|{FORBIDBLANKDOT})")
    sPattern = Replace(sPattern, "{ALLOWBLANKDOT}", ALLOWBLANKDOT)
    sPattern = Replace(sPattern, "{FORBIDBLANKDOT}", FORBIDBLANKDOT)
    sPattern = Replace(sPattern, "{SLASH}", SLASH)

    Dim oMatch As Match = Regex.Match(sDir, sPattern)

    Debug.Print("""" & sDir & """ returns """ & oMatch.Value & """")

    Return (sDir = oMatch.Value)
End Function

根据Microsoft specification for path names

,这确实可以捕获以下所有内容
[/]path name[/] 
[/]path name/path name/path name[/]
./path name[/]
./../path name/path name/path name[/]
../path name[/]
../../path name/path name/path name[/]
c:
c:path name[/]
c:path name/path name/path name/file name[/]
c:/path name[/]
c:/path name/path name/path name/file name[/]
c:.[/]
c:./path name[/]
c:./path name/path name/path name/file name[/]
c:..[/]
c:/../path name[/]
c:/../path name/path name/path name/file name[/]
\\?\c:path name[/]
\\server name/share name[/]
\\server name\share name\path name\path name[/]
\\?\UNC\server name\share name[/]

如果有人想出更优雅的作品,请告诉我