2008-11-05 62 views
0

我怎样才能创建一个字符串的正则表达式像这样:如何使用正则表达式处理像这样的字符串?

<SERVER> <SERVERKEY> <COMMAND> <FOLDERPATH> <RETENTION> <TRANSFERMODE> <OUTPUTPATH> <LOGTO> <OPTIONAL-MAXSIZE> <OPTIONAL-OFFSET> 

大多数领域都只是简单的话,但他们中的一些可能的路径,如FOLDERPATH,OUTPUTPATH,这些路径也可以带有文件名和通配符的路径。

保留是一个数字,传输模式可以是bin或ascii。问题是,LOGTO可能是日志文件名称追加的路径,也可能是NO,这意味着没有日志文件。

主要问题是可选参数,它们都是数字,如果没有MAXSIZE,则OFFSET不能存在,但MAXSIZE可以不带偏移地存在。

下面有一些例子:

loveserver love copy /muffin* 20 bin C:\Puppies\ NO 256 300 
loveserver love copy /muffin* 20 bin C:\Puppies\ NO 256 
loveserver love copy /hats* 300 ascii C:\Puppies\no\ C:\log\love.log 256 

现在的主要问题是,路径可以有空格他们,所以如果我使用。为了匹配所有内容,当解析LOG目标最终连接到输出路径的可选参数时,正则表达式最终破坏。

另外,如果我最终使用。并开始删除它的一部分,正则表达式将开始把东西放在它不应该的地方。

继承人我的正则表达式:

^(\s+)?(?P<SRCHOST>.+)(\s+)(?P<SRCKEY>.+)(\s+)(?P<COMMAND>COPY)(\s+)(?P<SRCDIR>.+)(\s+)(?P<RETENTION>\d+)(\s+)(?P<TRANSFER_MODE>BIN|ASC|BINARY|ASCII)(\s+)(?P<DSTDIR>.+)(\s+)(?P<LOGFILE>.+)(\s+)?(?P<SIZE>\d+)?(\s+)?(?P<OFFSET>\d+)?$ 

回答

1

只要分割空白是永远不会工作。但是,如果你可以对数据做出一些假设,就可以开展工作。

一些假设我脑子里想的:

  • SERVERSERVERKEYCOMMAND不包含任何空格:\S+
  • FOLDERPATH开始以斜线:/.*?
  • RETENTION是一个数字:\d+
  • 不包含任何空格的TRANSFERMODE\S+
  • OUTPUTPATH开始与驱动和带有斜线结束:[A-Z]:\\.*?\\
  • LOGTO要么是单词“NO”,或路径开始与驱动:[A-Z]:\\.*?
  • MAXSIZEOFFSET是一个数:\d+

全部放在一起:

^\s* 
(?P<SERVER>\S+)\s+ 
(?P<SERVERKEY>\S+)\s+ 
(?P<COMMAND>\S+)\s+ 
(?P<FOLDERPATH>/.*?)\s+ # Slash not that important, but should start with non-whitespace 
(?P<RETENTION>\d+)\s+ 
(?P<TRANSFERMODE>\S+)\s+ 
(?P<OUTPUTPATH>[A-Z]:\\.*?\\)\s+ # Could also support network paths 
(?P<LOGTO>NO|[A-Z]:\\.*?) 
(?: 
    \s+(?P<MAXSIZE>\d+) 
    (?: 
    \s+(?P<OFFSET>\d+) 
)? 
)? 
\s*$ 

在一个行:

^\s*(?P<SERVER>\S+)\s+(?P<SERVERKEY>\S+)\s+(?P<COMMAND>\S+)\s+(?P<FOLDERPATH>/.*?)\s+(?P<RETENTION>\d+)\s+(?P<TRANSFERMODE>\S+)\s+(?P<OUTPUTPATH>[A-Z]:\\.*?\\)\s+(?P<LOGTO>NO|[A-Z]:\\.*?)(?:\s+(?P<MAXSIZE>\d+)(?:\s+(?P<OFFSET>\d+))?)?\s*$ 

测试:

>>> import re 
>>> p = re.compile(r'^(?P<SERVER>\S+)\s+(?P<SERVERKEY>\S+)\s+(?P<COMMAND>\S+)\s+(?P<FOLDERPATH>/.*?)\s+(?P<RETENTION>\d+)\s+(?P<TRANSFERMODE>\S+)\s+(?P<OUTPUTPATH>[A-Z]:\\.*?\\)\s+(?P<LOGTO>NO|[A-Z]:\\.*?)(?:\s+(?P<MAXSIZE>\d+)(?:\s+(?P<OFFSET>\d+))?)?\s*$',re.M) 
>>> data = r"""loveserver love copy /muffin* 20 bin C:\Puppies\ NO 256 300 
... loveserver love copy /muffin* 20 bin C:\Puppies\ NO 256 
... loveserver love copy /hats* 300 ascii C:\Puppies\no\ C:\log\love.log 256""" 
>>> import pprint 
>>> for match in p.finditer(data): 
... print pprint.pprint(match.groupdict()) 
... 
{'COMMAND': 'copy', 
'FOLDERPATH': '/muffin*', 
'LOGTO': 'NO', 
'MAXSIZE': '256', 
'OFFSET': '300', 
'OUTPUTPATH': 'C:\\Puppies\\', 
'RETENTION': '20', 
'SERVER': 'loveserver', 
'SERVERKEY': 'love', 
'TRANSFERMODE': 'bin'} 
{'COMMAND': 'copy', 
'FOLDERPATH': '/muffin*', 
'LOGTO': 'NO', 
'MAXSIZE': '256', 
'OFFSET': None, 
'OUTPUTPATH': 'C:\\Puppies\\', 
'RETENTION': '20', 
'SERVER': 'loveserver', 
'SERVERKEY': 'love', 
'TRANSFERMODE': 'bin'} 
{'COMMAND': 'copy', 
'FOLDERPATH': '/hats*', 
'LOGTO': 'C:\\log\\love.log', 
'MAXSIZE': '256', 
'OFFSET': None, 
'OUTPUTPATH': 'C:\\Puppies\\no\\', 
'RETENTION': '300', 
'SERVER': 'loveserver', 
'SERVERKEY': 'love', 
'TRANSFERMODE': 'ascii'} 
>>> 
+0

太棒了。非常感谢你。 – UberJumper 2008-11-05 18:23:51

4

的问题是,因为你允许的文件名空间和使用空格分开场,解决的办法是不明确的。您或者需要使用不能出现在文件名中的不同字段分隔符,或者使用其他方法来表示文件名中带有空格的文件名,例如把它们放在引号中。

3

这在理论上是可行的,但是你正在为自己制造难以置信的难题。这里有许多问题:

1)您正在使用空格作为分隔符,并且您还允许在路径名称中使用空格。您可以通过强制应用程序使用不含空格的路径来避免这种情况。

2)最后有2个可选参数。这意味着以“C:\ LogTo Path 256 300”结尾的行不知道路径是否为C:\ LogTo Path 256 300,没有可选参数,或者C:\ Log To Path 256有一个可选参数或C: \ LogTo路径有2个可选参数。

这将很容易用输出替换算法进行修复。用下划线替换带下划线和下划线的空格。因此,在将日志文件分割为空格后,可以可靠地将其反转。

即使作为一个人,你也不可能100%可靠地执行这个功能。

如果您认为所有路径都以星号,反斜线或.log结尾,您可以使用积极向前查找路径的结尾,但没有关于此的某种规则,您将被塞满。

我觉得单一的正则表达式对于这个太难了,会让任何人试图维护代码疯狂。我是一个正则表达式妓女,尽可能地使用它们,我不会尝试这个。

0

您需要以正则表达式可以将它们与路径名区分开的方式来限制路径之间的字段。

所以,除非你把一个特殊的分离器,该序列

<OUTPUTPATH> <LOGTO> 

可选空间将无法正常工作。

如果路径看起来像这些字段,您可能会得到令人惊讶的结果。 例如

c:\ 12 bin \ 250 bin \output 

<FOLDERPATH> <RETENTION> <TRANSFERMODE> <OUTPUTPATH> 

是不可区分的。

所以,让我们试着限制所允许的字符位:

<SERVER>, <SERVERKEY>, <COMMAND> no spaces -> [^]+ 
<FOLDERPATH> allow anything -> .+ 
<RETENTION> integer -> [0-9]+ 
<TRANSFERMODE> allow only bin and ascii -> (bin|ascii) 
<OUTPUTPATH> allow anything -> .+ 
<LOGTO> allow anything -> .+ 
<OPTIONAL-MAXSIZE>[0-9]* 
<OPTIONAL-OFFSET>[0-9]* 

所以,我的东西走的

[^]+ [^]+ [^]+ .+ [0-9]+ (bin|ascii) .+ \> .+([0-9]* ([0-9]*)?)? 

的线用“>”分开的两个pathes。您可能需要引用路径名称。

注意:这是匆忙完成的。

-1

低于/高于允许值内?因为如果不是你有一个非常简单的解决方案:

只是刚刚“>”,分裂,是否将会取代次数的“>”的“> <”,并去掉所有低于/高于从每个项目更大。它可能比正则表达式的代码长,但它会更清晰地发生。

+0

<>不用于引用实际字符串中的标记 - 它们只是在提问者对字符串格式的规范中。 – mackenir 2008-11-05 18:22:15

相关问题