我想采用这样的字符串:
[One, Two[A, B[i, ii, iii, iv], C], Three]
并将其转换为列表层次结构,这样如果我执行如下代码:
Console.Write(myList[1][1][2]);
输出将是:
iii
我希望这是一个足够普遍的要求,有一些用 C# 编写的简单解析代码。
让我知道我的问题是否可以更清楚地表达。
我必须使用正则表达式。子字符串匹配和子表达式可以为您提供递归以获取 sub-sub-... 级别。
在 preg 中使用 /^\[(.+)\]$/ 之类的东西来收集单个级别的项目。处理它直到你不再收到一个级别,在你获得单个系列的胆量后在','上爆炸。
用 ',' 分割结果。
应该像
最后修剪左/右空间以获得完美的结果。
你追求的是数组还是列表?
这对于字符串来说是非常困难的,因为你必须处理空格,或者在元素中使用逗号等。
如果您可以控制此列表中的内容,我建议您查看 XML 或二进制序列化,它们具有帮助您执行此操作的库。
这不是一个实用的答案,但如果您能够使用 .NET 4.0 测试版,您可以查看微软正在为文本 DSL 开发的 Oslo(以及后续工具),这似乎正是您所需要的。
如果您有能力控制格式,我也会投票支持 XML 或 JSON 或其他格式。但是缺少这些,这是解析器的 Python 实现,因为我很无聊。
class ExprParser(object):
current = []
list_stack = []
def __init__(self):
pass
def parse(self,input):
for atom in [s.strip() for s in input.split(',')]:
self.parse_atom(atom)
return self.current
def do_pushes(self,atom):
""" Strip off the '[' and push new lists """
i = 0
while i < len(atom) and atom[i] == '[':
self.push()
i += 1
return atom[i:]
def do_pops(self,atom):
""" Pop the lists """
i = 0
while i < len(atom) and atom[i] == ']':
self.pop()
i += 1
def parse_atom(self,atom):
push_start = atom.find('[')
rest = self.do_pushes(atom[push_start:]) if push_start >= 0 else atom
pop_start = rest.find(']')
val = rest[:pop_start] if pop_start >= 0 else rest
self.add(val)
if pop_start >= 0:
self.do_pops(rest[pop_start:])
def push(self):
self.current = []
self.list_stack.append(self.current)
def pop(self):
done = self.list_stack.pop()
self.current = self.list_stack[-1] if self.list_stack else done
if self.current is not done:
self.add(done)
def add(self,val):
self.current.append(val)
像这样使用:
parser = ExprParser()
parser.parse('[One, Two[A, B[i, ii, iii, iv], C], Three]')
尽管对格式错误的输入没有错误处理。