使用java解析文件“/ etc / default”

时间:2010-04-19 16:53:52

标签: java regex parsing properties

我正在尝试使用java和正则表达式解析/etc/default中常见的配置文件。到目前为止,这是我在每个文件的每一行上迭代的代码:

// remove comments from the line
int hash = line.indexOf("#");
if (hash >= 0) {
    line = line.substring(0, hash);
}

// create the patterns
Pattern doubleQuotePattern = Pattern.compile("\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*=\\s*\"(.*)\"\\s*");
Pattern singleQuotePattern = Pattern.compile("\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*=\\s*\\'(.*)\\'\\s*");
Pattern noQuotePattern = Pattern.compile("\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*=(.*)");

// try to match each of the patterns to the line
Matcher matcher = doubleQuotePattern.matcher(line);
if (matcher.matches()) {
    System.out.println(matcher.group(1) + " == " + matcher.group(2));
} else {
    matcher = singleQuotePattern.matcher(line);
    if (matcher.matches()) {
        System.out.println(matcher.group(1) + " == " + matcher.group(2));
    } else {
        matcher = noQuotePattern.matcher(line);
        if (matcher.matches()) {
            System.out.println(matcher.group(1) + " == " + matcher.group(2));
        }
    }
}

这可以按照我的预期运作,但我很确定我可以通过使用更好的正则表达式来减小这种方式,但我没有运气。有人知道更好的方法来阅读这些类型的文件吗?

3 个答案:

答案 0 :(得分:2)

您可以使用antlr生成解析器。基本上你为你想要使用的语言编写语法(或者使用众多grammars already written中的一个语法,而antlr将为你生成一个解析器。

答案 1 :(得分:1)

在许多情况下,您可以使用java.util.Properties来处理shell配置文件。

实际上,如果你不使这些文件过于复杂,你可以在shell脚本和java程序之间以这种方式共享它们。

不能很好地处理的事情是引用的字符串。

答案 2 :(得分:1)

以下是您可以使用的单个模式,相当于上面的三个模式:

Pattern etcPattern = Pattern.compile(
   "\\s*([a-zA-Z_]\\w*)\\s*=\\s*"+
   "(\"|'|.{0,0})(.*?)\\2"+  //QUOTE MATCHING
   "\\s*");

这和你之间有三个不同之处:首先我将表达式[a-zA-Z0-9_]替换为其预定义的字符类\ w(单词字符)。第二部分(QUOTE MATCHING)是一种匹配和剥离外部平衡报价的模式,但也允许三种模式的不平衡报价。

首先使用模式(\“|'|。{0,0})。这是

  1. 双引号
  2. 单引号
  3. 任何零次
  4. 然后你的。*模式后跟反向引用\ 2。反向引用表示匹配模式2(引用模式)匹配的内容。这是上述第三种情况很重要的地方。如果值不以单引号或双引号开头,则需要能够忽略它。所以它首先尝试匹配其中一个引号。如果它不能那么它将匹配空字符串,这反过来允许反向引用匹配空字符串。

    使其工作的最后一项更改是将内部。*模式更改为不情愿(至。*?),以便在可能的情况下允许引号与后引用匹配并被剥离。

    所以你应该可以这样运行:

    Matcher matcher = etcPattern.matcher(line);
    if (matcher.matches()) {
        System.out.println(matcher.group(1) + " == " + matcher.group(3));
    }
    

    等同于上面的示例(请注意,值现在位于匹配组3中而不是两个。正如我所说,这与您的模式相匹配,特别是它将允许不平衡的引号,并允许任何内部引用该值。