【问题标题】:using awk sed to parse update puppet file使用 awk sed 解析更新 puppet 文件
【发布时间】:2013-12-16 14:52:35
【问题描述】:

我有一个包含多行代码的 puppet 文件,其中的部分如下所示:

$defaultrepo=myrepo
$defaultbranch=mybranch

gitmod::pullstuff {'othergitcode':
      gitcommit => "b54123be540adrwer3b65872384e0101c5f94c926b81",
      gitorg      => "${defaultrepo}",
      branch    => "${defaultbranch}",
    }

gitmod::pullstuff {'mygitcode':
      gitcommit => "b54123be540adrfer3b65872384e0101c5f94c926b81",
      gitorg      => 'awesomerepo',
      branch    => "master",
    }

它可以有任意数量的块,看起来类似于上面列出的两个代码块。

我正在寻找一种方法来解析文件并将值作为变量提取,然后使用它们来获取最新的 git commit 并更新值。我正在考虑 bash 脚本中的 awk 和 sed,以便它可以执行类似的操作。 例如

values could be: $gitrepo=mygitcode $gitorg=awesomerepo $gitbranch=master

for i in $(awk "regexto pull out each block from  gitmod::pullstuff \{'whatever': through         to the ending \}" puppetfile.pp);
do
    $gitrepo="sed/awk to pullout git repo"
    $gitorg="sed/awk to pullout git org"
    $gitbranch="sed/awk to pullout git branch"
    $newcommit=git ls-remote https://github.com/$gitorg/$gitrepo.git refs/heads/$gitbranch
    sed -i "replace commit with $newcommit"
done

我不是专业的开发人员,所以请多多包涵。有人可以指出一般结构应该是什么样子。不要担心正则表达式等我可以搞砸并弄清楚。只是想知道我怎样才能得到它,以便它单独处理它找到的每个“块”。出于某种原因,我无法让 awk 正确地将它们分开,并且会弄乱格式。

就像我可以做这样的事情:

awk "/gitmod::pullstuff/{a=4}{if(a-->0){print;next}}"

它会拉出我想要的一切。我需要以某种方式将其粘贴到 for 语句中,以便我可以将 awk 找到的每个实例视为一个单独的块,我也可以做一些事情。

【问题讨论】:

  • 欢迎来到 Stack Overflow。你能把你的问题说得更具体一点吗? “任何指针”不是一个具体的问题。如果您不确定要问什么,请尝试构建真正的解决方案,而不仅仅是伪代码。
  • 感谢您指出这一点。我只是做了一些编辑。我想我只是在寻找什么逻辑结构对实现我的目标有意义,我可以填写正则表达式等。
  • sed -i "replace commit with $newcommit" 是什么意思?
  • 基本上它将使用 $newcommit 创建的值来替换该块中相应的 gitcommit 例如gitcommit = "b54123be540adrwer3b65872384e0101c5f94c926b81 可以替换为 gitcommit => "199561c5f55bb2e77bf022a6b294bs63f3c74d9"
  • 我刚刚添加了另一个编辑。我基本上只是想弄清楚如何让 bash/awk 将每个找到的实例视为一个单独的块,我也可以做一些事情。

标签: git bash sed awk puppet


【解决方案1】:

你可以试试这样的:

awk -f m.awk puppetfile.pp  puppetfile.pp

m.awk 在哪里:

NR==FNR {
    if (/^gitmod/) {
        gitrepo=getRepo()
        getline
        getline
        gitorg=getOrg()
        getline
        branch=getBranch()
        com[++i]=getNewCommit()
    }
    else if (/^\$[[:alnum:]]*=/) {
        vn=getVarName()
        val=getVarValue()
        var[vn]=val
    }
    next
}

/^gitmod/ {
    print
    getline
    sub(/".*"/,"\""com[++j]"\"")
}
{ print }

function getVarValue(a) {
    match($0,/=([[:alnum:]]+)[[:blank:]]*/,a)
    return a[1]
}

function getVarName(a) {
    match($0,/\$([[:alnum:]]+)=/,a)
    return "${"a[1]"}"
}

function getNewCommit(cmd,var) {
    cmd="ls-remote https://github.com/"gitorg"/"gitrepo".git refs/heads/"branch
    cmd |& getline var
    return var
}

function getBranch(a,br) {
    match($0,/"(.*)"/,a)
    br=a[1]
    if (br in var) br=var[br]
    return br
}

function getOrg(a,org) {
    match($0,/"(.*)"/,a)
    org=a[1]
    if (org in var) org=var[org]
    return org
}
function getRepo(a,rep) {
    match($0,/\{"(.*)":/,a)
    rep=a[1]
    if (rep in var) rep=var[rep]
    return rep
}

【讨论】:

  • 谢谢。我想这就是我正在寻找的东西
  • @Luke 我已经更新了我的答案以包括变量插值,并且进一步假设双引号。如果使用变量插值,则必须使用带花括号的语法"${var}",它无法识别没有大括号的变量,例如"$var"..
  • @Luke 请注意,您必须将 puppet 文件中的所有单引号更改为双引号。你仍然有很多单引号。例如'othergitcode'..
  • 谢谢。我可以不使用变量插值来解决。这应该对我有用。非常感谢您的帮助。
【解决方案2】:

这里对您的问题有不同的看法。如果您将所有这些数据存储在 YAML 文件中:

gits:
  othergitcode:
    gitcommit: "b54123be540adrwer3b65872384e0101c5f94c926b81"
    gitorg:    "myreop",
    branch:    "mybranch",
  mygitcode:
    gitcommit: "b54123be540adrfer3b65872384e0101c5f94c926b81",
    gitorg:    'awesomerepo',
    branch:    "master"

然后你可以用这样的东西把它放在木偶上:

create_resources('gitmod::pullstuff', hiera('gits'))

这使得使用任何脚本语言都可以轻松操作(awk 除外,我想这个答案在这里不够用......)。

【讨论】:

    猜你喜欢
    • 2015-01-12
    • 2018-03-31
    • 1970-01-01
    • 2013-02-06
    • 2022-11-30
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2012-04-16
    相关资源
    最近更新 更多