如何解析类似csv的定义并从shell脚本构建依赖集?

时间:2016-06-09 13:02:21

标签: bash shell

考虑 roles 的定义,其中每一行都是空的,注释(以哈希符号为前缀)或角色定义。角色定义由名称后跟冒号和无,一个或多个空格分隔的角色依赖项组成:

# this is a comment

somerole: role2 role3
role2: role3
# 'empty' roles should be supported as well
roled:
anotherrole: somerole role2

我想以一种我可以迭代它们的方式在bash函数中获取所有依赖角色。它们只需要按正确的顺序列出一次,例如如果role1依赖于role2,而role2依赖于role3,则顺序必须是 role3,role2,role1 ,而不是 role1,role2,role3 。保证定义文件不包含任何循环依赖。

我可以通过遍历每个条目来解析角色文件(非常天真,确实如此),如

for role in $(cat "$ROLEFILE" |grep -v -e '^$' -e '#'); do
    # test if name ends with colon
    echo $role|grep -qe ':$'
    if [ $? -eq 0 ]; then
        # remove last character
        role=$(echo $role|sed 's/.$//')
        echo "new role definition: $role"
    else
        echo "role depenency: $role"
    fi
done

但是,我如何构建唯一的依赖关系集,并收集给定输入角色的依赖关系?

这是一个示例调用的样子。每个依赖项都需要在依赖于它的角色之前打印。最终的角色始终是我们要求的角色。

$ ./testroles somerole
role3 role2 somerole
$ ./testroles roled
roled
$ ./testroles anotherrole
role3 role2 somerole anotherrole

生成的脚本应该与Ubuntu 14.04和OS X一起使用。

2 个答案:

答案 0 :(得分:1)

为什么不逐行解析文件?

while read line; do 
  dep=$(echo $line | cut -d ":" -f2)
  role=$(echo $line | cut -d ":" -f1)
  echo "$dep $role"
  # or do anything you want...  
done < $ROLEFILE

答案 1 :(得分:1)

我创建了下面的脚本,它就像你描述的那样打印依赖树。它使用shell_map来创建角色依赖关系的映射。

#!/bin/bash
source shell_map.sh

ROLE_ARG="$1"
ROLEFILE=input.sh

# create a new map where roles are keys and deps are values
shell_map new roles_map

while read line; do 
    #skip comments
    [[ $line =~ ^#.*$ ]] && continue;

    #skip blank lines
    [[ "$line" =~ ^[[:alpha:]]+ ]] || continue;

    deps=$(echo $line | cut -d ":" -f2)
    role=$(echo $line | cut -d ":" -f1)

    # put in the map
    roles_map put $role "$deps"
done < $ROLEFILE

# this map will store the dependency tree without repetitions
shell_map new deps_tree

function role_deps {
    local role=$1
    local my_deps=`roles_map get $role`

    [ -z "$my_deps" ] && return 0

    for dep in $my_deps; do
        deps_tree put $dep ""
        for inherited_dep in `role_deps $dep`; do
            deps_tree put $inherited_dep ""
        done;
    done

    # echoes the dependencies stored in the map
    deps_tree keys
}

echo `role_deps $ROLE_ARG` $ROLE_ARG