2016-09-27 126 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