【问题标题】:Parsing an input markup解析输入标记
【发布时间】:2014-07-01 11:26:35
【问题描述】:

我正在尝试解析表单的标记-

!TAG1 VAL1=0.88 VALARRAY=0. 0. 0.8 !TAG2 VAL2=0.998 !END !END'  

就标记而言,我知道这是表示不带引号的真实向量的一种相当糟糕的方式。但它是在我正在处理的旧代码中解析的,我不想更改“标准”输入格式。
我已经实现了一个 do while 循环来解析这个 - 程序逐字遍历字符串(单词=不包含空格)和两个计数器 - 一个坚持最后一个 = 的单词位置和second 查找包含= 的下一个单词。有什么好的pythonic迭代器可以咀嚼每个VAR=VALUE对的想法吗?

EDIT1:这是我的解决方案,尽管经过多次迭代后我得到了它。因此它不是很可读!

s1='!TAG1 VAL1=0.88 VALARRAY=0. 0. 0.8 !TAG1 VAL2=0.998 !END !END'
list=[]
word=''
for s in s1.split():
    if (s[0]=='!'):
        if word : list.append(word)
        list.append(s) 
        word=''
    else :
        if '=' in s:
            if word : list.append(word)
            word=s
        else:
            word=(word+" "+s).strip()
if word: list.append(word)

print s1
print list

输出是-

!TAG1 VAL1=0.88 VALARRAY=0. 0. 0.8 !TAG1 VAL2=0.998 !END !END
['!TAG1', 'VAL1=0.88', 'VALARRAY=0. 0. 0.8', '!TAG1', 'VAL2=0.998', '!END', '!END']

希望这会有所帮助!

【问题讨论】:

  • 您要忽略! 前面的单词吗?换句话说,你能从你给定的例子中给出例子匹配吗?
  • 确实如此,给我几分钟 :)

标签: python regex python-2.7 iterator


【解决方案1】:

说明:

 (?# capture valueless keys)
 !          (?# match !)
 (          (?# start capturing group)
  \S+       (?# match non-whitespace characters)
 )          (?# end capturing group)
|           (?# OR)
 (?# capture key/value pairs)
 (          (?# start capturing group)
  \S+?      (?# lazily match non-whitespace)
 )          (?# end capturing group)
 =          (?# match literal =)
 (          (?# start capturing group)
  [^=]+?    (?# lazily match anything but =)
 )          (?# end capturing group)
 (?# values have a loose definition, so we need to lookahead for a delimiter)
 (?=        (?# start lookahead)
  \s*       (?# match optional whitespace)
  (?:       (?# start non-capturing group)
    \S+?=   (?# match another key)
   |        (?# OR)
    !\S+    (?# match another key w/o value)
   |        (?# OR)
    $       (?# match end of the string)
  )         (?# end non-capturing group)
 )          (?# end lookahead)

Regex101


可视化:

Debuggex


注意事项:

您的无价值键 (!TAG) 将位于第一个捕获组中,键/值对 (VAL1=0.88) 将分别位于第二/第三个捕获组中。无价值键很简单,只需匹配 !,然后捕获任何非空白字符 (\S = [^\r\n\t\f ])。键/值对更难,我们从非空白字符开始,然后是=,然后是任何非=(OP 提到的没问题)。但是,我们需要一种方法来阻止值继续到字符串的末尾。所以我们使它成为一个惰性匹配,然后向前查找空格,然后是:另一个键/值、另一个无值键或字符串的结尾。


别忘了缩小版;)

!(\S+)|(\S+?)=([^=]+?)(?=\s*(?:\S+?=|!\S+|$))

【讨论】:

  • 虽然我一直在寻找更易读的解决方案,但您的解决方案完全难以辨认让我大吃一惊:)!果然这确实像我打算的那样工作,使用一些 re.iterator 对象。谢谢!
  • 哈哈,我尽量解释清楚了。如果没有强分隔符(如空格或用双引号括起来的值),解析会变得很复杂。而!TAG1 键只是增加了另一个难度。如果有任何需要进一步解释的地方,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多