通过{}括号分隔的元素解析文本文件

时间:2011-02-17 16:16:18

标签: linux parsing shell grep

有没有办法通过包含{} s分隔的元素的txt文件进行解析

以下是文件中的示例:

virtual vs_devtnet_80 {
   snat automap
   pool pool_devtnet_80
   destination 167.69.107.41:http
   ip protocol tcp
   profiles {
      profile_http_health {}
      tcp-lan-optimized {}
   }
}
virtual vs_devdpp_4430 {
   snat automap
   pool pool_devdpp_5430
   destination 167.69.107.31:https
   ip protocol tcp
   persist devdpp
   profiles tcp-lan-optimized {}
}
virtual vs_devwww30_80 {
   snat automap
   pool pool_devwww30_80
   destination 167.69.107.46:http
   ip protocol tcp
   profiles {
      profile_http_health {}
      tcp-lan-optimized {}
   }
}

如您所见,元素是分开的,但是{}

任何帮助都会很高兴。我试图使用grep,但它只返回一行...

我希望能够通过最顶层的元素进行搜索,例如searh.sh virtual vs_devtnet_80,并让它返回整个blob ..此外,或许能够搜索顶层和其中一个子层图层,例如search.sh virtual vs_devtnet_80 pool,它将返回pool_devtnet_80

5 个答案:

答案 0 :(得分:0)

类似的东西:

cat .tmp | sed '/.*{/ ! { s/.*//g}'

这不会完全解决它,但我认为它做的类似于你想要的东西

答案 1 :(得分:0)

看看JSON pasers,它们是用各种语言编写的,语法看起来很相似,可以给你一些关于如何解决这个问题的想法。

基本上你需要做的是有一个递归函数,只要遇到'{'就调用它自己,并在遇到'}'时返回内容。 我写了一篇关于类似lisp的解析器的文章,实际上就是这样做的。在这里查看灵感:http://www.codeproject.com/KB/linq/TinyLisp.aspx

Rgds Gert-Jan

答案 2 :(得分:0)

这应该会给你第二个'blob',例如:

sed -n '/virtual vs_devdpp_4430.*/,/^}$/p' filename.txt

并通过grep -oP '(?<=pool ).*'管道以获取该blob中pool后的内容。

答案 3 :(得分:0)

这是Tcl语法,因此您可以设置一种机制来将其作为Tcl脚本运行,从而创建自己的数据结构。

#!/usr/bin/env tclsh

# create a safe slave interpreter
set slave [interp create -safe]

# set up the slave to parse the input file
$slave eval {
    proc virtual {subkey body} {
        eval $body
    }
    proc unknown {cmd args} {
        upvar 1 subkey subkey  ;# access the 'subkey' variable from the 'virtual' proc
        if {[llength $args] == 1} {set args [lindex $args 0]}
        dict set ::data $subkey $cmd $args
    }
    set data [dict create]
}
$slave expose source

# now do the parsing in the slave
$slave eval source [lindex $argv 0]

# fetch the data structure
set data [$slave eval set data]

# and do stuff with it.
dict for {subkey subdict} $data {
    puts "$subkey destination = [dict get $subdict destination]"
}

然后,parser.tcl input_file输出

vs_devaetnet_80 destination = 167.69.107.41:http
vs_devdpp_4430 destination = 167.69.107.31:https
vs_devwww30_80 destination = 167.69.107.46:http

答案 4 :(得分:0)

我最终必须创建一个递归函数,该函数首先使用strpos在整个配置文件中查找搜索变量。然后使用弹出的递归函数并弹出括号以返回搜索变量的整个主体。