2014-09-06 81 views
1

我需要一些正則表達式guru的幫助。與條件匹配的塊

我正在嘗試爲家庭項目製作一個小型配置系統,但爲此我覺得需要更多的正則表達式代碼,而不是我的正則表達式技巧。

我需要能夠根據條件和操作提取塊內的一些信息。舉一個例子。

action1 [condition1 condition2 !condition3] { 
    Line 1 
    Line 2 
    Line 3 
} 

條件存儲在由空格分隔的簡單變量中。我使用這些變量來創建用於從文件中提取塊信息的正則表達式。大多數,如果這工作正常,除了我不知道如何使「不匹配」的部分,這基本上意味着一個「單詞」是不可用的條件變量。

VAR1="condition1 condition2" 
VAR2="condition1 condition2 condition3" 

當與上述匹配時,它應該匹配VAR1而不是VAR2。

這是我迄今爲止

PARAMS="con1 con2 con3" 
INPUT_PARAMS="[^!]\\?\\<$(echo $PARAMS | sed 's/ /\\>\\|[^!]\\?\\</g')\\>" 

sed -n "/^$ACTION[ \t]*\(\[\($INPUT_PARAMS\)*\]\)\?[ \t]*{/,/}$/p" default.cfg | sed '/^[^{]\+{/d' | sed '/}/d' 

不知道如何漂亮,這是的,但它的工作,除了不匹配。

編輯:

好吧,我會盡量詳細一點。

比方說,我有下面的文本/ config文件

​​

,我有休耕條件來匹配

ARG1="con1 con2 con3" 
ARG2="con1 con2" 
ARG3="con1" 
ARG4="con1 con4" 

# Matching against ARG1 should print Line A, B, D and E 
# Matching against ARG2 should print Line C, D and E 
# Matching against ARG3 should print Line E 
# Matching against ARG4 should print Line E 

下面是使用正常的條件檢查類似例子1動作的一個java 。它給出了一個更好的主意,我想做

if (ARG2.contains("con1") && ARG2.contains("con2") && !ARG2.contains("con3")) { 
    // Print all lines in this block 
} 
+0

我什麼都不懂。你想做什麼 ?檢查比賽並知道何時不匹配? – 2014-09-06 20:29:12

+0

您正在使用錯誤的工具。 sed是在單行上進行簡單替換的正確工具,但對於任何其他文本操作,您應該使用awk。發佈一些清晰,準確的樣本輸入和預期的輸出以及對地圖的描述,我們可以爲您提供幫助。 – 2014-09-06 21:58:20

+0

如果你實際解析的是CSS,你有沒有考慮過使用實際的CSS解析器? – tripleee 2014-09-07 10:29:39

回答

3

你是如何選擇的哪些記錄打印線的邏輯是從我不清楚所以這裏是如何創建套用awk積極和消極條件:

$ cat tst.awk 
BEGIN{ 
    RS = ""; FS = "\n" 

    # create the set of the positive conditions in the "conds" variable. 
    n = split(conds,tmp," ") 
    for (i=1; i<=n; i++) 
     wanted[tmp[i]] 
} 
{ 
    # create sets of the positive and negative conditions 
    # present in the first line of the current record. 
    delete negPresent # use split("",negPresent) in non-gawk 
    delete posPresent 
    n = split($1,tmp,/[][ {]+/) 
    for (i=2; i<n; i++) { 
     cond = tmp[i] 
     sub(/^!/,"",cond) ? negPresent[cond] : posPresent[cond] 
    } 

    allPosInWanted = 1 
    for (cond in posPresent) 
     if (!(cond in wanted)) 
      allPosInWanted = 0 

    someNegInWanted = 0 
    for (cond in negPresent) 
     if (cond in wanted) 
      someNegInWanted = 1 

    if (allPosInWanted && !someNegInWanted) 
     for (i=2;i<NF;i++) 
      print $i 
} 

$ awk -v conds='con1 con2 con3' -f tst.awk file 
    Line A 
    Line B 
    Line D 
    Line E 
$ 
$ awk -v conds='con1 con2' -f tst.awk file 
    Line C 
    Line D 
    Line E 
$ 
$ awk -v conds='con1' -f tst.awk file 
    Line E 
$ 
$ awk -v conds='con1 con4' -f tst.awk file 
    Line E 
$ 

,現在你只需要任何邏輯,你在打印正在做的條件在各組的比較是最後一塊喜歡的代碼。

+0

這看起來不錯。然而,通緝不應該是積極的或消極的,他們是可用的條件。所以它應該做的是檢查所有posPresent是否存在於conds中,而consent中是否存在negPresent。如果是這種情況,那麼它應該打印駐留在該塊的兩個大括號內的所有行。如果沒有,那麼應該打印該塊的任何內容。不知道如何用awk做到這一點,因爲我從來沒有用過它。我知道它很強大,但我還沒有時間去玩弄它。 – 2014-09-07 09:33:50

+0

好吧,我只是在當前條件下對所描述的幾個循環進行了編碼,並針對所需條件進行了測試。現在看看解決方案。如果你只需要'{...}'而不是整個塊之間的界限,這是一個微不足道的調整。你可以在沒有Present集的情況下做更簡單的操作,但它們有助於提高清晰度,並允許您編寫簡單的完整性檢查,例如檢查posPresent和negPresent中存在的條件,或者填充時已存在的條件他們。獲得這本書:有效的Awk編程,第三版。 – 2014-09-07 10:08:47

+0

是的,這是我需要的行爲。因爲我需要它跳過評論#並且只打印大括號內的行,但是這讓我對awk的工作原理有所瞭解,因此我將進一步研究這個示例。非常感謝:) – 2014-09-07 10:18:32