.NET 解决方案——投机
这个建议的 .NET 解决方案只是“建议的”;我不使用 .NET,也无法在我的任何机器上对其进行测试(是否有 .NET 的正则表达式测试网站?)。我已经采用了有效的 Perl 解决方案,删除了您不担心的部分<mark>
和<pad>
注释,并在假设 .NET 没有类似于 Perl 的x
选项的易读性选项的情况下将其全部展平到一行. 您仍然可以找到对应于 Perl 正则表达式的 5 个部分的 5 组括号。我假设这(?:...)
是一个非捕获组。
(?:-{1,2}|/)(?<name>\w+)(?:[=:]?|\s+)(?<value>[^-\s"][^"]*?|"[^"]*")?(?=\s+[-/]|$)
我还假设 .NET 提供了一些类似于 Perlg
修饰符的机制,它允许您在第二次(或后续)遍历中扫描字符串,它在上一次遍历中停止。或者您可以以某种方式确定比赛结束的位置并从那里恢复扫描。
Perl 解决方案 — 已验证
这与我设法使用 Perl 正则表达式(在 Mac OS X 10.7.5 上使用 Perl 5.16.0 测试)一样好。
#!/usr/bin/env perl
use strict;
use warnings;
# Original regex split into 5 sections:
# C1 (?<=(^-{1,2}|\ -{1,2}|^/|\ /))
# C2 (?<name>[\w]+)
# C3 [ :"]*
# C4 (?<value>[\w.?=&+ :/|\\]*)
# C5 (?=[ "]|$)
my $rx = qr%(?<mark> -{1,2}|/ ) (?# Was C1)
(?<name> \w+ ) (?# Was C2)
(?<pad> (?: [=:]?|\s+ )) (?# Was C3)
(?<value> (?: [^-\s"][^"]*? | "[^"]*" ))? (?# Was C4)
(?=\s+[-/]|$) (?# Was C5)
%x;
while (my $line = <DATA>)
{
chomp $line;
print "\nLine: $line\n";
while ($line =~ m/$rx/g)
{
my($mark, $name, $pad, $value) = ($1, $2, $3, $4 // "");
print "Found: mark $mark name <<$name>> pad <<$pad>> value <<$value>>\n";
}
}
__DATA__
-s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
-o:"C:\temp\db\" -s -r -host:localhost --d theDB
-s -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\" -h:localhost -d:theDB
-s -d http://www.theproject.com -h:localhost -d:theDB
-i:"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\" --h:localhost -d:theDB
-h:localhost -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack_1_5\db\DB Scripts\" -d:theDB
--d theDB -o:"C:\temp\db\" -host=local-host -r
-s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
/d theDB /o:"C:\temp\db\" /host=local-host /r
/d theDB /o:"C:\temp\db\" /host=local-host /r /t
-s:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
大部分脚本不是很有趣。__DATA__
外部 while 循环一次一行读取文件的数据部分(即标记后的材料),将其打印以进行验证,然后在该行重复运行正则表达式以查找组件(标记、名称、填充和值),将它们打印出来。大部分数据是问题中提供的(谢谢!)。与最初提供的数据相比,最后三行数据是额外的。
所有的兴奋都在正则表达式中。我使用 Perl 的/x
修饰符在正则表达式中允许空格以提高可读性。这意味着除非前面有反斜杠或用方括号括起来,否则空格并不重要(并且此样本中没有重要的空格)。我已经使用(?<name> ...)
符号来识别原始片段,尽管名称可以省略,因为它们没有被使用。这些(?# Was Cn)
部分是纯粹的评论。
- 标记是一个或两个破折号或斜线;
--?
将是另一种更短的编写方式。
- 名称是一串字母数字;这并不试图强制“第一个字符可能不是数字”。
- 填充将名称与值分开。它可以是单个等号或冒号,也可以是一串空格。内部
(?: ...)
是非捕获分组运算符。
- 该值是可选的(
-s
样本数据第一行第一个位置的选项没有值)。它由以下部分组成: 以破折号、双引号或空格以外的其他内容开头的字符串,后跟非引号的非贪婪字符串;或一个双引号、一串非引号和另一个双引号。
- 尾随零宽度上下文 (C5) 是一个或多个空格字符,后跟一个破折号或斜线,或 EOS。因为值模式是非贪婪的,所以贪婪的尾随上下文会吞噬选项值之后的尾随空格。
输出是:
Line: -s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<i>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: -o:"C:\temp\db\" -s -r -host:localhost --d theDB
Found: mark - name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark - name <<s>> pad <<>> value <<>>
Found: mark - name <<r>> pad <<>> value <<>>
Found: mark - name <<host>> pad <<:>> value <<localhost>>
Found: mark -- name <<d>> pad << >> value <<theDB>>
Line: -s -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\" -h:localhost -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<i>> pad <<:>> value <<"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB -Scripts\">>
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: -s -d http://www.theproject.com -h:localhost -d:theDB
Found: mark - name <<s>> pad << >> value <<>>
Found: mark - name <<d>> pad << >> value <<http://www.theproject.com>>
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\" --h:localhost -d:theDB
Found: mark - name <<i>> pad <<:>> value <<"C:\Users\Fozzie\Workspace\TheProject\TheProject_Stack_1_5\db\DB Scripts\">>
Found: mark -- name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: -h:localhost -i:"C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack_1_5\db\DB Scripts\" -d:theDB
Found: mark - name <<h>> pad <<:>> value <<localhost>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: --d theDB -o:"C:\temp\db\" -host=local-host -r
Found: mark -- name <<d>> pad << >> value <<theDB>>
Found: mark - name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark - name <<host>> pad <<=>> value <<local-host>>
Found: mark - name <<r>> pad <<>> value <<>>
Line: -s -i:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad <<>> value <<>>
Found: mark - name <<i>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>
Line: /d theDB /o:"C:\temp\db\" /host=local-host /r
Found: mark / name <<d>> pad << >> value <<theDB >>
Found: mark / name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark / name <<host>> pad <<=>> value <<local-host >>
Found: mark / name <<r>> pad <<>> value <<>>
Line: /d theDB /o:"C:\temp\db\" /host=local-host /r /t
Found: mark / name <<d>> pad << >> value <<theDB>>
Found: mark / name <<o>> pad <<:>> value <<"C:\temp\db\">>
Found: mark / name <<host>> pad <<=>> value <<local-host>>
Found: mark / name <<r>> pad <<>> value <<>>
Found: mark / name <<t>> pad <<>> value <<>>
Line: -s:C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\ -h:local:host -d:theDB
Found: mark - name <<s>> pad <<:>> value <<C:\Users\Fozzie\Workspace\TheProject\TheProject-Stack-1_5\db\DB Scripts\>>
Found: mark - name <<h>> pad <<:>> value <<local:host>>
Found: mark - name <<d>> pad <<:>> value <<theDB>>