sed或awk有多个条件

时间:2018-07-26 06:33:53

标签: bash awk sed

我有些文件看起来像这样

LiveData

我想解析每个文件,并对定义 service {} 之间的每个节执行以下操作:

  • 如果我在 service_description 行上找到了一项键盘输入(在另一个用作参考的文件中列出),我想检查gen-infra是否存在于 use ,否则我需要在gen-svc之前添加它。

  • 如果在 service_description 行上,我找不到列出的关键字之一,并且如果 gen-appli 行上不存在< em>使用,添加它!

示例:

如果找到 check2 ,则应添加gen-infra(如果不存在),因此上面的节应为

define host{
            use                             gen-host
            host_name                       AA1234
            ......
            }

define service{
            use                             gen-perf,gen-infra,gen-svc
            host_name                       AA1234
            service_description             check1
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

define service{
            use                             gen-svc
            host_name                       AA1234
            service_description             check2
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

define service{
            use                             gen-appli,gen-svc
            host_name                       AA1234
            service_description             check3
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

define service{
            use                             gen-perf,gen-svc
            host_name                       AA1234
            service_description             check4
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

define service{
            use                             gen-appli,gen-svc
            host_name                       AA1234
            service_description             check5
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

check4 不在参考列表中,所以如果不存在,我应该添加gen-appli,因此上面的节应为

define service{
            use                             gen-infra,gen-svc
            host_name                       AA1234
            service_description             check2
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

使用sed,如果找到列出的关键字之一,我设法添加了 gen-infra ;如果找不到任何关键字,则添加了 gen-appli

define service{
            use                             gen-perf,gen-appli,gen-svc
            host_name                       AA1234
            service_description             check4
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }

$ {INFRA_LST}包含基于参考文件的关键字列表。 $ {INFRA_LST}如下所示(当然还有更多的关键字):

sed -i "/define service/,/}/{H;d;};x;/service_description\s*${INFRA_LST}/! s/use\s*\([[:graph:]]*\)\(gen-svc\)\(.*\)/use\t\t\t\t\1gen-appli,\2\3/g" FILE_TO_PARSE.txt
sed -i "/define service/,/}/{H;d;};x;/service_description\s*${INFRA_LST}/ s/use\s*\([[:graph:]]*\)\(gen-svc\)\(.*\)/use\t\t\t\t\1gen-infra,\2\3/g" FILE_TO_PARSE.txt

在现实生活中,我可以拥有除gen-svc之外的其他东西,因此可以解释该组,因为其中存在OR条件。

但是,如果尚不存在 gen-infra gen-appli ,如何添加第二条条件呢? >

1 个答案:

答案 0 :(得分:0)

我在bash中的解决方案。
sed是解析行的简单好工具,对于多行解析,使用适当的语言更简单。
脚本规则为:

  1. 如果在服务中service_description标签等于字符串check2,则程序应在gen-infra标签中添加名称use
  2. 如果服务中的service_description标签与字符串check4不相等,则程序应在gen-appli标签中添加名称use
  3. use标记中名称的顺序无关紧要,并用,逗号分隔。
  4. 标签use中至少已经有一个名称。

#!/bin/bash
set -euo pipefail

assert() { if ! eval "$1"; then echo "Assertion '$1' failed!" >&2; exit 1; fi; }

add_name_to_use() {
    local service name
    service=$1
    name=$2
    sed '/^[[:space:]]*use[[:space:]]*/{/'"$name"'/b;s/$/,'"$name"'/}' <<<"$service"
}

cmp_service_description() {
    local service value
    service=$1
    shift
    greparg='^[[:space:]]*service_description[[:space:]]*\('
    for i; do
        greparg+="$i\\|"
    done
    greparg=$(sed 's/\\|$//'<<<"$greparg")
    greparg+='\)$'
    grep -q "$greparg" <<<"$service"
}

handle_one_service() {
    local service
    service=$1
    # If I find check2,
    if cmp_service_description "$service" "check2" "keyword2" "and so on..."; then
        # I should add gen-infra if not present
        service=$(add_name_to_use "$service" "gen-infra")
    fi
    # if check4 is not in the reference list
    if ! cmp_service_description "$service" "check4"; then
        # I should add gen-appli
        service=$(add_name_to_use "$service" "gen-appli")
    fi
    echo "$service"
}

inservice=false
str=""
while IFS= read -r line; do
    str+="$line"$'\n'
    case "$line" in
    "define service{")
        inservice=true
        ;;
    *"}"*)
        if "$inservice"; then
            inservice=false
            handle_one_service "$str"
        else
            echo "$str"
        fi
        str=""
        ;;
    esac
done

我已经编写了函数cmp_service_description,因此您可以检查多个(列表)值。
将输出与输入列进行比较。在原始文件的左侧,在脚本输出的右侧:

$ paste -d'#' 1 <(./parse.sh <1) | column -t -s'#' -o' | '
define host{                                                           | define host{
            use                             gen-host                   |             use                             gen-host
            host_name                       AA1234                     |             host_name                       AA1234
            ......                                                     |             ......
            }                                                          |             }
                                                                       | 
define service{                                                        | 
            use                             gen-perf,gen-infra,gen-svc | define service{
            host_name                       AA1234                     |             use                             gen-perf,gen-infra,gen-svc,gen-appli
            service_description             check1                     |             host_name                       AA1234
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             service_description             check1
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }                                                          |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             }
define service{                                                        | 
            use                             gen-svc                    | define service{
            host_name                       AA1234                     |             use                             gen-svc,gen-infra,gen-appli
            service_description             check2                     |             host_name                       AA1234
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             service_description             check2
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }                                                          |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             }
define service{                                                        | 
            use                             gen-appli,gen-svc          | define service{
            host_name                       AA1234                     |             use                             gen-appli,gen-svc
            service_description             check3                     |             host_name                       AA1234
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             service_description             check3
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }                                                          |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             }
define service{                                                        | 
            use                             gen-perf,gen-svc           | define service{
            host_name                       AA1234                     |             use                             gen-perf,gen-svc
            service_description             check4                     |             host_name                       AA1234
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             service_description             check4
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
            }                                                          |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             }
define service{                                                        | 
            use                             gen-appli,gen-svc          | 
            host_name                       AA1234                     | define service{
            service_description             check5                     |             use                             gen-appli,gen-svc
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             host_name                       AA1234
            xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy            |             service_description             check5
            }                                                          |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             xxxxxxxxxxxxxxx                 yyyyyyyyyyyyyyy
                                                                       |             }