匹配具有条件的块

时间:2014-09-06 19:07:44

标签: regex bash awk sed

我需要一些regexp 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'

不确定这是多么漂亮,但它确实有效,除了不匹配。

修改

好的,我会尝试详细说明一下。

我们说我有以下文字/配置文件

action1 [con1 con2 con3] {
    Line A
    Line B
}

action2 [con1 con2 !con3] {
    Line C
}

action3 [con1 con2] {
    Line D
}

action4 {
    Line E
}

我有与之匹配的休假条件

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

以下是使用正常条件检查的action2示例。它更好地了解了我正在尝试的内容

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

1 个答案:

答案 0 :(得分: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
$

现在你只需要在最后一个块中编写你喜欢的逻辑来进行打印,以比较每个集合中的条件。