java - 正则表达式几乎适用于 JSON,但不完全适用

标签 java regex

大家好,我正在尝试将一个格式良好的字符串解析为其组成部分。该字符串非常像 JSON,但严格来说它不是 JSON。它们的形成方式如下:

createdAt=Fri Aug 24 09:48:51 EDT 2012, id=238996293417062401, text='Test Test', source="Region", entities=[foo, bar], user={name=test, locations=[loc1,loc2], locations={comp1, comp2}}

将输出视为文本 block ,此时无需执行任何特殊操作。

createdAt=Fri Aug 24 09:48:51 EDT 2012 
id=238996293417062401 
text='Test Test' 
source="Region"
entities=[foo, bar] 
user={name=test, locations=[loc1,loc2], locations={comp1, comp2}}

使用以下表达式,我可以将大部分字段分开

,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))(?=(?:[^']*'[^']*')*(?![^']*'))

这将在所有不在任何类型的引号中的逗号上进行分割,但我似乎无法跳转到它在不在括号或大括号中的逗号上分割的位置。

最佳答案

因为您想要处理嵌套的括号/括号,所以处理它们的“正确”方法是单独标记它们,并跟踪您的嵌套级别。因此,您确实需要针对不同 token 类型的多个正则表达式,而不是单个正则表达式。

这是 Python,但转换为 Java 应该不会太难。

# just comma
sep_re = re.compile(r',')

# open paren or open bracket
inc_re = re.compile(r'[[(]')

# close paren or close bracket
dec_re = re.compile(r'[)\]]')

# string literal
# (I was lazy with the escaping. Add other escape sequences, or find an
# "official" regex to use.)
chunk_re = re.compile(r'''"(?:[^"\\]|\\")*"|'(?:[^'\\]|\\')*[']''')

# This class could've been just a generator function, but I couldn;'t
# find a way to manage the state in the match function that wasn't
# awkward.
class tokenizer:
  def __init__(self):
    self.pos = 0

  def _match(self, regex, s):
    m = regex.match(s, self.pos)
    if m:
      self.pos += len(m.group(0))
      self.token = m.group(0)
    else:
      self.token = ''
    return self.token

  def tokenize(self, s):
    field = '' # the field we're working on
    depth = 0  # how many parens/brackets deep we are
    while self.pos < len(s):
      if not depth and self._match(sep_re, s):
        # In Java, change the "yields" to append to a List, and you'll
        # have something roughly equivalent (but non-lazy).
        yield field
        field = ''
      else:
        if self._match(inc_re, s):
          depth += 1
        elif self._match(dec_re, s):
          depth -= 1
        elif self._match(chunk_re, s):
          pass
        else:
          # everything else we just consume one character at a time
          self.token = s[self.pos]
          self.pos += 1
        field += self.token
    yield field

用法:

>>> list(tokenizer().tokenize('foo=(3,(5+7),8),bar="hello,world",baz'))
['foo=(3,(5+7),8)', 'bar="hello,world"', 'baz']

此实现需要一些捷径:

  • 字符串转义确实很懒:它只支持双引号字符串中的 \" 和单引号字符串中的 \'。这很容易修复。<
  • 它仅跟踪嵌套级别。它验证括号与括号(而不是方括号)匹配。如果您关心这一点,您可以将深度更改为某种堆栈并将其插入/弹出括号/括号。

关于java - 正则表达式几乎适用于 JSON,但不完全适用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14714584/

相关文章:

r - 使用带有多个分隔符的 strsplit

regex - Excel中的表达式语法?

java - Eclipse Helios中有哪些新功能?

java.util.Map$Entry 未解析

java - 正则表达式 获取所有索引

javascript - 如何检查字符串是否与javascript中的正则表达式匹配?

python - 为最后一个空格拆分字符串的最佳方法

正则表达式捕获排除组的组

java - 求小于指定数的任意数的倍数之和。我的错误在哪里?

java - 获得两组点之间最近对的最佳组合