2014-09-06 80 views
1

我需要一些正则表达式guru的帮助。与条件匹配的块

我正在尝试为家庭项目制作一个小型配置系统,但为此我觉得需要更多的正则表达式代码,而不是我的正则表达式技巧。

我需要能够根据条件和操作提取块内的一些信息。举一个例子。

action1 [condition1 condition2 !condition3] { 
    Line 1 
    Line 2 
    Line 3 
} 

条件存储在由空格分隔的简单变量中。我使用这些变量来创建用于从文件中提取块信息的正则表达式。大多数,如果这工作正常,除了我不知道如何使“不匹配”的部分,这基本上意味着一个“单词”是不可用的条件变量。

VAR1="condition1 condition2" 
VAR2="condition1 condition2 condition3" 

当与上述匹配时,它应该匹配VAR1而不是VAR2。

这是我迄今为止

PARAMS="con1 con2 con3" 
INPUT_PARAMS="[^!]\\?\\<$(echo $PARAMS | sed 's/ /\\>\\|[^!]\\?\\</g')\\>" 

sed -n "/^$ACTION[ \t]*\(\[\($INPUT_PARAMS\)*\]\)\?[ \t]*{/,/}$/p" default.cfg | sed '/^[^{]\+{/d' | sed '/}/d' 

不知道如何漂亮,这是的,但它的工作,除了不匹配。

编辑:

好吧,我会尽量详细一点。

比方说,我有下面的文本/ config文件

​​

,我有休耕条件来匹配

ARG1="con1 con2 con3" 
ARG2="con1 con2" 
ARG3="con1" 
ARG4="con1 con4" 

# Matching against ARG1 should print Line A, B, D and E 
# Matching against ARG2 should print Line C, D and E 
# Matching against ARG3 should print Line E 
# Matching against ARG4 should print Line E 

下面是使用正常的条件检查类似例子1动作的一个java 。它给出了一个更好的主意,我想做

if (ARG2.contains("con1") && ARG2.contains("con2") && !ARG2.contains("con3")) { 
    // Print all lines in this block 
} 
+0

我什么都不懂。你想做什么 ?检查比赛并知道何时不匹配? – 2014-09-06 20:29:12

+0

您正在使用错误的工具。 sed是在单行上进行简单替换的正确工具,但对于任何其他文本操作,您应该使用awk。发布一些清晰,准确的样本输入和预期的输出以及对地图的描述,我们可以为您提供帮助。 – 2014-09-06 21:58:20

+0

如果你实际解析的是CSS,你有没有考虑过使用实际的CSS解析器? – tripleee 2014-09-07 10:29:39

回答

3

你是如何选择的哪些记录打印线的逻辑是从我不清楚所以这里是如何创建套用awk积极和消极条件:

$ cat tst.awk 
BEGIN{ 
    RS = ""; FS = "\n" 

    # create the set of the positive conditions in the "conds" variable. 
    n = split(conds,tmp," ") 
    for (i=1; i<=n; i++) 
     wanted[tmp[i]] 
} 
{ 
    # create sets of the positive and negative conditions 
    # present in the first line of the current record. 
    delete negPresent # use split("",negPresent) in non-gawk 
    delete posPresent 
    n = split($1,tmp,/[][ {]+/) 
    for (i=2; i<n; i++) { 
     cond = tmp[i] 
     sub(/^!/,"",cond) ? negPresent[cond] : posPresent[cond] 
    } 

    allPosInWanted = 1 
    for (cond in posPresent) 
     if (!(cond in wanted)) 
      allPosInWanted = 0 

    someNegInWanted = 0 
    for (cond in negPresent) 
     if (cond in wanted) 
      someNegInWanted = 1 

    if (allPosInWanted && !someNegInWanted) 
     for (i=2;i<NF;i++) 
      print $i 
} 

$ awk -v conds='con1 con2 con3' -f tst.awk file 
    Line A 
    Line B 
    Line D 
    Line E 
$ 
$ awk -v conds='con1 con2' -f tst.awk file 
    Line C 
    Line D 
    Line E 
$ 
$ awk -v conds='con1' -f tst.awk file 
    Line E 
$ 
$ awk -v conds='con1 con4' -f tst.awk file 
    Line E 
$ 

,现在你只需要任何逻辑,你在打印正在做的条件在各组的比较是最后一块喜欢的代码。

+0

这看起来不错。然而,通缉不应该是积极的或消极的,他们是可用的条件。所以它应该做的是检查所有posPresent是否存在于conds中,而consent中是否存在negPresent。如果是这种情况,那么它应该打印驻留在该块的两个大括号内的所有行。如果没有,那么应该打印该块的任何内容。不知道如何用awk做到这一点,因为我从来没有用过它。我知道它很强大,但我还没有时间去玩弄它。 – 2014-09-07 09:33:50

+0

好吧,我只是在当前条件下对所描述的几个循环进行了编码,并针对所需条件进行了测试。现在看看解决方案。如果你只需要'{...}'而不是整个块之间的界限,这是一个微不足道的调整。你可以在没有Present集的情况下做更简单的操作,但它们有助于提高清晰度,并允许您编写简单的完整性检查,例如检查posPresent和negPresent中存在的条件,或者填充时已存在的条件他们。获得这本书:有效的Awk编程,第三版。 – 2014-09-07 10:08:47

+0

是的,这是我需要的行为。因为我需要它跳过评论#并且只打印大括号内的行,但是这让我对awk的工作原理有所了解,因此我将进一步研究这个示例。非常感谢:) – 2014-09-07 10:18:32