简洁地比较和部分合并配置树

时间:2010-11-23 05:07:37

标签: parsing configuration diff

我想简洁地区分配置文件树,其中大多数是平面的(即键/值对),但其中一些是XML,bash脚本或自定义格式。配置信息几乎总是没有排序,可以包含空格和注释。

对于平面文件,执行没有空格的diff或对排序输出的注释非常接近我想要做的事情。对于XML,some tools available。但是,一些自定义格式例如嵌套配置。键的顺序并不重要,子键的顺序并不重要,但树结构(很像XML)。其他人则依赖于订单。

如果你不得不经常这样做,你会怎么做呢?那里有什么工具足够通用吗?滚动我自己的解决方案怎么样?格式的数量也不是很大(肯定没有/ etc那么糟糕),默认是平的 - 也许是一些libmagic和文件名匹配,结合自定义解析器?有没有人尝试过类似的东西?

一种方法是尝试通过对具有嵌套但无序结构的文件执行体面工作来解决95%的问题,并使用现有工具对其他一些类型进行特殊套管。你能建议一个简单的嵌套文件的主要工作方法吗?

一些例子:

com.example.resource.host=foo
com.example.resource.port=8080

VS

com.example.resource.port=8080
com.example.resource.host=bar
//com.example.network.timeout=600
com.example.network.timeout=300

应该产生

< com.example.resource.host=foo
---
> com.example.resource.host=bar
> //com.example.network.timeout=600
> com.example.network.timeout=300

或可选:

< com.example.resource.host=foo
---
> com.example.resource.host=bar
> com.example.network.timeout=300
正如你所料的那样。但是,像:

Conf com.example.resource =
    Conf host = foo;
    Conf port = 8080;
;

VS

Conf com.example.resource =
    Conf port = 8080;
    Conf host = bar;
;
Conf com.example.network =
    Conf timeout = 300;
;

也应该有效:

<     Conf host = foo
---
>     Conf host = bar
> Conf com.example.network =
>     Conf timeout = 300;
> ;

1 个答案:

答案 0 :(得分:1)

每个配置文件都有语法和隐含的语义。看来你想要做的是用隐含的语义而不是文本来比较配置文件。

执行此操作的唯一方法是为每种配置文件类型提供自定义解析器。然后,您需要根据隐含的语义来比较文件。

一般来说,这很难做到,当然对于真正的编程语言来说。我们提供折衷解决方案,调用SmartDifferencers根据精确的语言语法解析代码,然后根据语言结构(例如,表达式,语句,声明,方法......)对它们进行比较,将差异报告为抽象编辑操作(在块内移动,复制,删除,插入,重命名标识符)。这给了程序员有意义的术语(这就是你所要求的),而不仅仅是“这个以某种方式改变的行块”的典型差异。

这些工具知道语言语法,他们知道语义的 tiny 位;特别是,我们尝试(并且我们并非完全存在于所有这些中)来处理这个概念 交换语言元素。在Java中,类中方法的顺序并不重要。在您的情况下,某些配置元素的顺序可能并不重要。我们的机器可以考虑到这一点。

要为想要做的事情做到这一点,你需要为每种类型的配置文件单独的解析器,并且当你可以安全地随机移动命令时,为每种类型提供单独的知识。您需要为每种类型的配置文件使用单独的工具才能正确执行此操作。 (那些基于XML的文件实际上需要separtes工具,因为您试图区分语义和语法。)。我认为,您理想的解决方案是针对每种配置文件类型的SmartDifferencers。