2016-09-27 76 views
0

我有这样的结构:嵌套大括号AWK正则表达式

label1 { 
    label1_1 { 

     item1_1_1: "value1_1_1"; 
     label1_1_2:{ item1_1_2_1: "value1_1_2_1";}; 

     item1_1_3: "value1_1_3"; 
    }; 

    label1_2 {...}; 
    ... 
}; 

label2 { 
    item2_1: "value2_1"; 
    label2_1:{ 
     item2_1_1: "value2_1_1"; 
     ... 
    }; 
}; 

该部分可能在一个行或者多行,和空行像样。我试图用awk获得与给定的标签名称的任何部分,

section=$(awk -v RS='' -v ORS='\n\n' "/($2)\s(\{([^{}]|(?R)|\n)*\})/" $1) 

在$ 1文件名,$ 2是标签名称。如果在该部分没有出现空行,例如“label2”,但它会被其他人显示出来,它就会起作用。

什么是我应该使用正确的正则表达式?

+2

'awk'不支持PCRE递归模式 – anubhava

+1

为了扩展@ anubhava的声明 - 没有awk支持的正则表达式可以做你想做的事。你可以在awk中做你想要的,当然,不要用正则表达式。所以 - 你需要一个awk解决方案还是一个正则表达式的解决方案?另外,如果引用字符串中可能出现'{'或'}'或换行符,例如'item1_1_1:“value {1_1_1}”''然后将这些案例包含在您的示例输入/输出中,因为它们使得工作与其他工作截然不同。考虑并包含脚本可能难以处理的内容,而不仅仅是简单的案例。 –

+0

谢谢你的回复,我对awk太不熟悉了,不知道如何将tst.awk嵌入到我的bash脚本中,因为我希望所有的东西都可以在一块。如果awk太难做到,我们可以使用其他命令,你知道哪个命令可以实现这个目标吗? – user3593261

回答

3

这里有一种方法做你想要什么,假设既不{也不}可引用的字符串内出现,并使用GNU AWK 4 *的一对夫妇的扩展:

$ cat tst.awk 
BEGIN { RS="^$" } 
{ 
    tmp = $0 
    while (match(tmp,/(\<([[:alnum:]_]+):?\s*{[^{}]+};)/,a)) { 
     start[a[2]] = RSTART 
     lgth[a[2]] = RLENGTH 
     tmp = substr(tmp,1,RSTART-1) sprintf("%*s",length(a[1]),"") substr(tmp,RSTART+RLENGTH) 
    } 
} 
label in start { print substr($0,start[label],lgth[label]) } 

$ awk -v label='label2' -f tst.awk file 
label2 { 
    item2_1: "value2_1"; 
    label2_1:{ 
     item2_1_1: "value2_1_1"; 
     ... 
    }; 
}; 

$ awk -v label='label1_1' -f tst.awk file 
label1_1 { 

     item1_1_1: "value1_1_1"; 
     label1_1_2:{ item1_1_2_1: "value1_1_2_1";}; 

     item1_1_3: "value1_1_3"; 
    }; 

$ awk -v label='label1_1_2' -f tst.awk file 
label1_1_2:{ item1_1_2_1: "value1_1_2_1";}; 

您可以拨打AWK无论是作为或awk -f scriptfile inputfile所以awk 'script' inputfile使用上述awk脚本内联,而不是存储在一个文件就是:

awk ' 
BEGIN { RS="^$" } 
{ 
    tmp = $0 
    while (match(tmp,/(\<([[:alnum:]_]+):?\s*{[^{}]+};)/,a)) { 
     start[a[2]] = RSTART 
     lgth[a[2]] = RLENGTH 
     tmp = substr(tmp,1,RSTART-1) sprintf("%*s",length(a[1]),"") substr(tmp,RSTART+RLENGTH) 
    } 
} 
label in start { print substr($0,start[label],lgth[label]) } 
' file