正则表达式需要匹配从文件名派生文件路径的文件路径。

时间:2013-05-29 14:36:02

标签: regex powershell

我的驱动器包含超过800万个文件,是CRM系统的文件存储区域。文件以特定格式存储,每个文件应在数据库中具有匹配的记录。然而,由于一些非常糟糕的安全性,世界和妻子也在同一个驱动器上创建文件。我的任务是使用Powershell和正则表达式识别我正在执行的无效文件。 典型的有效文件路径如下所示:

P:\PERSON\06\19\09\619090.5577930.DOC

所有文件都在名为P:的驱动器上,其中包含四个子目录:EVENT,OPPORTUN,ORGANISA或PERSON。每个子目录包含可变数量的子目录,其名称范围为00到99,文件名是由句点分隔的两组数字,后跟扩展名。

我用来匹配这种模式的正则表达式是:

^P:\\(EVENT|OPPORTUN|ORGANISA|PERSON)\\(\d{2}\\)+\d+\.\d+\.\w{3,4}$

复杂的是,有效文件在文件名中的第一组数字和子目录路径之间也有关系:

删除最后一位数字。

如果数字的长度现在是奇数,则添加前导零。

将结果数分成对,这应该是路径。

所以使用上面的例子:

第一组数字是:619090

删除最后一位数字:61909

长度为奇数,因此添加前导零:061909

分成对:06 \ 19 \ 09

我的问题是这个逻辑可以合并到我的正则表达式中吗,有没有办法使用前向或后向引用?

2 个答案:

答案 0 :(得分:2)

我试图想出一些东西,如果powershell支持反向引用,你可以试试这个:

^P:\\(?:EVENT|OPPORTUN|ORGANISA|PERSON)\\(?:0(\d)|(\d{2}))\\(\d{2})\\(?P<t>\d{2})\\(?:(?:\1|\2)\3\4)0?\.\d+\.\w{3,4}$

\1\4是指之前找到的不同捕获组。

我在regex101上测试了一些字符串。

唯一的是它也会接受P:\OPPORTUN\61\90\90\619090.5577930.DOC我不太确定如何只使用一个正则表达式来解决这个问题...或者使正则表达式比已经存在的时间更长(这可能会超过两倍)。

如果你想真正确定它的时间差不多两倍:

^P:\\(?:EVENT|OPPORTUN|ORGANISA|PERSON)\\0(\d)\\(\d{2})\\(\d{2})\\(?:\1\2\3)0\.\d+\.\w{3,4}|P:\\(?:EVENT|OPPORTUN|ORGANISA|PERSON)\\(\d{2})\\(\d{2})\\(\d{2})\\(?:\4\5\6)\.\d+\.\w{3,4}$

编辑:最多7对数字:

^P:\\(?:EVENT|OPPORTUN|ORGANISA|PERSON)\\(?:0(\d)|(\d\d))\\(?:(\d\d)\\)?(?:(\d\d)\\)?(?:(\d\d)\\)?(?:(\d\d)\\)?(?:(\d\d)\\)?(?:(?:\1|\2)\3?\4?\5?\6?\7?)0?\.\d+\.\w{3,4}

答案 1 :(得分:0)

Jerry的回答指出了我正确的方向,并发现你可以拥有非捕获组中包含的捕获组。下面是我的正则表达式以及一些测试:

$samples = @()
$samples += 'P:\PERSON\06\19\09\619090.5577930.DOC' #good
$samples += 'P:\PERSON\19\09\19090.5577930.DOC' #good
$samples += 'P:\PERSON\10\10\10\06\19\09\1010100619090.5577930.DOC' #good
$samples += 'P:\PERSON\06\19\09\619090a.5577930.DOC' #bad
$samples += 'P:\PERSON\06\19\09\61909090.5577930.DOC' #bad
$samples += 'P:\PERSON\06\19\09\6190905577930.DOC' #bad

$regex = '^P:\\(?:EVENT|OPPORTUN|ORGANISA|PERSON)\\'
$regex += '(?:(\d)(\d)\\|0(\d)\\)(?:(\d{2})\\)?(?:(\d{2})\\)?(?:(\d{2})\\)?(?:(\d{2})\\)?(?:(\d{2})\\)?'
$regex += '(?:\1\2|\3)\4?\5?\6?\7?\8?\d?\.\d+\.\w{3,4}$'

$samples | % {
    $_ -match $regex

}