2015-01-10 22 views
0

structureA在文件中出現多次,並且必須分別在numUnitsA,numUnitsB,numUnitsC下對參數1的值進行求和,以計算structureA的所有出現次數。來自文件中各行的總和值

structureA { 
    numUnitsA { 
     parameter1 = 2 
    }  
    numUnitsB { 
     parameter1 = 4 
    }  
    numUnitsC { 
     parameter1 = 3 
    }  
} 

我用下面來獲取值,但如何總結他們如:

numUnitsA parameter1=6 
numUnitsB parameter1=9 
numUnitsC parameter1=9 

代碼:

while read -r line 
do 
if grep -q "parameter1" "$filename"; then 
    echo $(awk 'BEGIN{FS="="}{print $2}') 
fi 
done < "$filename" 
+0

縮進你的代碼。 – gsamaras

回答

1

試試這個:

awk -F'= *' '/parameter1/ { 
    if (++numUnit % 3 == 1) {par1 += $2} 
    else if (numUnit % 3 == 2) {par2 += $2} 
    else {par3 += $2} 
} 
END {print "numUnitsA parameter1=" par1 
    print "numUnitsA parameter1=" par2 
    print "numUnitsA parameter1=" par3}' "$filename" 

無循環的真正原因。這會將文件作爲參數並查找「numUnitX」的出現次數,獲取下一行並將該值添加到與X相對應的總值中。最後,它將打印總計。

替代答案:

$ cols=$(($(grep parameter1 $filename | wc -l)/3)) 
$ grep parameter1 "$filename" | sed 's/.*= //' | pr -ts"+" --columns "$cols" | bc 

這將得到的所有值,然後粘貼單元A,B和C值彼此相鄰在不同的行,由一個「+」分離,並計算出總和使用bc。輸出是三行,分別包含單位A,B和C的總數。

更新 回答現在只要參數不緊跟numUnits標籤。

說明

AWK是把一個文件分成記錄(將它們看作行,即使他們可以多行)和字段(想到這些欄目,與前一個程序評論仍然有效)。這些記錄和字段的分隔可以由用戶定義,但默認分隔符是記錄的換行符和字段的選項卡。因此,文件結構的定義如下:

record1: field1 field2 spaces allowed field 3 
record2: this record has only one field 

record4: the previous line was an empty record 
record5: in awk you can refer to fields using $1, $2, $3. like this: 
$1 in your code means this field $2 in code this field $3 $4 
record7: $0 is the variable for the entire record! 

的字段可以使用$1$2等加以解決,特殊$0是指整個記錄。兩個簡單的例子來說明。首先我們打印整個文件,渲染腳本相當於catawk '{print} file' or awk'{print $ 0}'文件. A second example changes every record (i.e. line as default) to the literal string不模擬awk : awk'{$ 0 =「don'\」'mock awk「}'文件. Note the special care to output a' 。

Builtins一些強大的awk內建變量可供我們使用,有些將在下面解釋。

  • FS字段分隔符,默認FS = "\t"
  • RS記錄分隔符,默認RS = "\n"
  • OFS輸出字段分隔符,默認OFS = " "
  • ORS輸出記錄分隔符,默認ORS = "\n"
  • NR當前記錄數,最後這是文件中的記錄數。
  • NF此記錄中的字段數。
  • FILENAME正在處理的文件的文件名。

這些是非常有用的變量,當打印輸出字段分隔符OFS時會自動插入。下面的示例代碼打印第一行的前兩個字段,由一個空格分隔(OFS通過使用空格插入)。 awk 'NR == 1 {print $1, $2}' file

結構基本AWK結構如下:

awk -F'= ' ' 
# this is a comment (starting with #) 
# begin clause 
BEGIN { 
    # do stuff BEFORE parsing the file 
    FS = "= +" # this is also achieved using the -F flag above 
    ... 
} 
/some regex/ { 
    # code here will be executed if record contains 'some regex' 
    # example: count number of lines that match this regex 
    count++ # increment count with one 
} 
NR == 1 { 
    # code here will only be executed on the first record 
} 
{ 
    # code right here will always be executed (i.e. for every record) 
    # note the regex is missing => match every record 
    ... 
} 
# add more clauses to match certain records before the end clause: 
END { 
    # execute code AFTER all files (you can read multiple files) have been parsed 
    print count # print number of records containing our regex 
}' path/to/some/file_to_parse /another/path/to/another/file 

基本上代碼包裹在大括號如果前面,則返回true,則執行它是否是一個正則表達式被在記錄(/regex notation/)找到或一個邏輯比較。當條件不足時,代碼將始終執行。

解決方案代碼分析

正如你看到的,我們沒有一個BEGIN條款,只有一個記錄條款。我們正在尋找記錄,在我們的案例中,包含字符串'parameter1'的行。這些正是包含我們想要總結的值的行。

我們將字段分隔符設置爲正則表達式= +表示等號和一個或多個空格。請注意,我們感興趣的記錄,這意味着我們有兩個記錄:

 paramter1 = 4 
     field1  |||field 2, 

這意味着$2現指4。請注意,$2在以下記錄中將爲空:paramter1=4,因爲等號後沒有空格。

現在我們有箱子的開關:等效

  1. numUnit相當於1個模3
  2. numUnit被2模3
  3. numUnit相當於3模3.

請注意,我們首先有if (++numUnit ...,這會在評估表達式之前增加變量numUnit (所以在if檢查條件之前)。正如你所看到的,awk不是強類型的,所以不需要先聲明numUnit。在第一次增加時,awk會假設它是零,因爲你試圖添加一些東西,而他不知道它是什麼。

因此numUnit每增加一次,我們就會找到一條包含paramter1的記錄。由於第一次將numUnit評估爲1,然後遵循模式1 2 0 1 2 0 ...'和'nunUnit'模式爲numUnitA numUnitB numUnitC numUnitA numUnitB ...,您可以看到每個這些案例都處理一種類型的所有記錄。每個案例現在都會將參數的值添加到它的總數中(正如您現在可以在代碼中輕鬆查看的那樣)。

最後,我們通過打印出信息來結束awk腳本,請記住,只有在所有記錄被讀取後纔會執行一次。這應該很清楚。

我強烈建議閱讀awk,它是一種非常強大的腳本語言,允許許多高級編程語言的構造。起初可能看起來很難,但這完全值得!

+0

謝謝@ShellFish。備選答案搜索參數1,因此不管文件中參數1的位置如何。你能否建議在第一個腳本中做相同的修改。 – user2610

+0

@ user2610你說得對,我解決了這個問題。當然,如果在某些結構中numUnitsB在numUnitsA之前,程序將無法正常工作。如果這可能發生,我將不得不添加幾行。 – ShellFish

+0

thanks [email protected]正常工作。請分享腳本中使用的邏輯。我不熟悉腳本。 – user2610