我目前正在嘗試編寫一個awk腳本來處理一堆DNS區域文件。但是,我遇到了某個DNS區域記錄(即TXT記錄形式的SPF和DKIM記錄)中存在空格的問題,這會導致awk將區域記錄的數據解釋爲多個字段。但是,他們共享的一個一致特徵是TXT記錄的數據總是用雙引號括起來,並且它總是最後一個實際字段。如何在awk中捕獲一個文本字符串作爲單個字段?
這裏有一對夫婦的SPF記錄樣本DNS區域只是爲了顯示輸入文件的結構:
; cPanel first:11.34.1.7 (update_time):1380693490 Cpanel::ZoneFile::VERSION:1.3 hostname:bentley.websitewelcome.com latest:11.36.2.4
; Zone file for digdeepdns.net
$TTL 14400
digdeepdns.net. 86400 IN SOA ns1.digdeepdns.net. slucas.digdeepdns.net. (
2013100200 ;Serial Number
14400 ;refresh
7200 ;retry
3600000 ;expire
14400 ;minimum
)
digdeepdns.net. 86400 IN NS ns1.digdeepdns.net.
digdeepdns.net. 86400 IN NS ns2.digdeepdns.net.
digdeepdns.net. 14400 IN A 192.185.57.22
localhost 14400 IN A 127.0.0.1
digdeepdns.net. 14400 IN MX 0 digdeepdns.net.
mail 14400 IN CNAME digdeepdns.net.
www 14400 IN CNAME digdeepdns.net.
ftp 14400 IN A 192.185.57.22
digdeepdns.net. IN TXT "v=spf1 ip4:70.84.243.130 a mx ip4:192.185.57.216 include:websitewelcome.com ~all"
cpanel 14400 IN A 192.185.57.22
webmail 14400 IN A 192.185.57.22
whm 14400 IN A 192.185.57.22
webdisk 14400 IN A 192.185.57.22
ns1 14400 IN A 192.185.57.216
ns2 14400 IN A 192.185.57.22
hg 14400 IN A 192.185.57.22
www.hg 14400 IN A 192.185.57.22
hg IN TXT "v=spf1 ip4:70.84.243.130 +a +mx +ip4:192.185.57.216 ?all"
webdisk.hg IN A 192.185.57.22
的域分隔每條記錄可以是一個標籤或字符串空間。你也可以看到,並非所有的記錄都有明確定義的TTL,所以我不能認爲2美元將成爲一個數字,3美元將成爲'IN'字面值。 SOA之後所有行中唯一共同的線索是$ 1,可以很容易地被/[-_0-9a-z.]+/
捕獲。我不打算進行精確和驗證;這些DNS區域由一個腳本生成,幾乎可以確保它們符合RFC 1035。
的DNS區域目前正在通過以下awk腳本處理:
#! /opt/local/bin/awk -f
BEGIN { OFS = "\t" }
NR < 11 { print }
NR > 10 && /("[^"]+")/ { print }
這裏的腳本示例輸出到目前爲止,不幸的是忽略了每一行-except-兩個是SPF記錄,但至少證明/("[^"]+")/
就像一個魅力正則表達式:
; cPanel first:11.34.1.7 (update_time):1380693490 Cpanel::ZoneFile::VERSION:1.3 hostname:bentley.websitewelcome.com latest:11.36.2.4
; Zone file for digdeepdns.net
$TTL 14400
digdeepdns.net. 86400 IN SOA ns1.digdeepdns.net. slucas.digdeepdns.net. (
2013100200 ;Serial Number
14400 ;refresh
7200 ;retry
3600000 ;expire
14400 ;minimum
)
digdeepdns.net. IN TXT "v=spf1 ip4:70.84.243.130 a mx ip4:192.185.57.216 include:websitewelcome.com ~all"
hg IN TXT "v=spf1 ip4:70.84.243.130 +a +mx +ip4:192.185.57.216 ?all"
第一10行區域文件的可以忽略不計(並且由腳本因此印刷直出);無論如何他們需要一些手動處理。但第11行和以後需要更好的對齊方式,我打算用printf來完成。
我從一開始就想弄清楚自己在做什麼,但最終我將使用printf來替換帶有製表符的空格,以便我可以使列更加整齊。但是,由於IFS必須是空格,因此這提出了一個挑戰,即我的DNS區域中的少數TXT記錄中的文本數據必須以某種方式混合在一起,並被解釋爲與printf一起使用的單個輸入字段。因此,正則表達式可以在雙引號內捕捉整個文本。
我正在awk中專門尋求解決方案(或者至少是一個非常有用的提示,可以引導我解決問題),因爲此學習體驗專門針對awk。我確信我可以想出一個方法,這可以很容易地完成,但這不是我最終目標的重點。
在這個問題上我有點頭大,我真的可以用一些幫助。
編輯:
關於建議,這裏的期望輸出的一個樣本(表格可能會有點borked,但基本要點是對所有其他的第1列3個標籤空間,以及1片) :
; cPanel first:11.34.1.7 (update_time):1380693490 Cpanel::ZoneFile::VERSION:1.3 hostname:bentley.websitewelcome.com latest:11.36.2.4
; Zone file for digdeepdns.net
$TTL 14400
digdeepdns.net. 86400 IN SOA ns1.digdeepdns.net. slucas.digdeepdns.net. (
2013100200 ;Serial Number
14400 ;refresh
7200 ;retry
3600000 ;expire
14400 ;minimum
)
digdeepdns.net. 86400 IN NS ns1.digdeepdns.net.
digdeepdns.net. 86400 IN NS ns2.digdeepdns.net.
digdeepdns.net. 14400 IN A 192.185.57.22
localhost 14400 IN A 127.0.0.1
digdeepdns.net. 14400 IN MX 0 digdeepdns.net.
mail 14400 IN CNAME digdeepdns.net.
www 14400 IN CNAME digdeepdns.net.
ftp 14400 IN A 192.185.57.22
digdeepdns.net. IN TXT "v=spf1 ip4:70.84.243.130 a mx ip4:192.185.57.216 include:websitewelcome.com ~all"
cpanel 14400 IN A 192.185.57.22
webmail 14400 IN A 192.185.57.22
whm 14400 IN A 192.185.57.22
webdisk 14400 IN A 192.185.57.22
ns1 14400 IN A 192.185.57.216
ns2 14400 IN A 192.185.57.22
hg 14400 IN A 192.185.57.22
www.hg 14400 IN A 192.185.57.22
hg IN TXT "v=spf1 ip4:70.84.243.130 +a +mx +ip4:192.185.57.216 ?all"
webdisk.hg IN A 192.185.57.22
最終的問題是我怎麼能有AWK過程中,第一場3-4(取決於是否$ 2是一個數字或「IN」)像正常的,那麼對於場5+,還需要成爲一個有條件的。引號中的任何內容都必須作爲單個字段進行處理。我強烈建議或指點,以幫助我找到解決方案。
編輯#2:
在一個有點關係但同時無關側切。我似乎無法找到一個明確的答案,它是否是可以嵌套模式{聲明}對作爲報表中的模式{聲明}子句,像這樣:
patternA {
patternAA { statements }
patternAB { statements }
}
patternB {
patternBA { statements }
patternBB { statements }
}
這可能在AWK ?如果是這樣,那可能會幫助我弄清楚如何執行此腳本。
很多的東西在這裏。很難說出你最終的問題。根據上面的示例輸入,您是否可以重新編輯您的問題以包含必需的輸出?雖然很多人都喜歡在awk中使用裸的規則/動作對,但是您可能會發現某些形式爲'awk'{if(N $ <11){print} else if(...){something else}; else {do this}}'input'可能會更適合打印出前10行的情況(例如)。祝你好運。 – shellter
你可以在std'/ pattB/{if($ 0〜patternBA){...}中嵌套模式測試,否則if($ 0〜patternBB){...} else {...}}你要!。祝你好運。 – shellter