2017-05-01 20 views
1

我有許多主機文件。我從所有服務器收集它們,並將它們放在host_files.txt中,然後我必須爲所有服務器創建一個主機文件。主機文件爲所有服務器創建一個唯一的文件

我做這個命令做一個獨特的文件,但有些行共享相同的IP地址或主機名。

awk '!a[$0]++' host_files.txt 

這裏是我的host_files.txt

#backup server IPs 
95.23.23.56 
95.23.23.57 

#ftp server IPs 
45.89.67.5 
45.89.67.3 

#apache 
12.56.35.36 
12.56.35.35 

#ftp server IPs 
95.23.23.50 

#apache 
12.56.35.37 

我要輸出的文件,但我需要保持註釋行

#backup server IPs <= comment line, i need to keep them 
95.23.23.56 
95.23.23.57 

#ftp server IPs <= comment line, i need to keep them 
45.89.67.5 
45.89.67.3 
95.23.23.50 

#apache <= comment line, i need to keep them 
12.56.35.36 
12.56.35.35 
12.56.35.37 

我已經嘗試:

sort -ur host_files.txt 

cat host_files.txt | uniq > ok_host.txt 

我需要ip沒有#只是n EED IP住址請幫我

在此先感謝

回答

1

在GNU AWK使用多維數組:

$ awk ' 
/^#/ { k=$0; next }   # group within identical comments, k is key to hash 
/./ { a[k][$1]=$0 }   # remove empty records and hash ips 
END { for(k in a) {   # after everything, output 
      print k 
      for(i in a[k]) 
       print a[k][i] 
    } 
}' file* 
#apache 
12.56.35.35 #apacheprivate 
12.56.35.36 #apachepub 
12.56.35.37 #apachepub 
#ftp server IPs 
45.89.67.3 #ftpssh 
45.89.67.5 #ftpmain 
95.23.23.50 #ftp 
#backup server IPs 
95.23.23.56 #masterbasckup 
95.23.23.57 #agentbasckup 

輸出是隨機的順序,因爲for(k in a),即。組內的評論組和ips沒有特定的順序。

+0

@詹姆斯布朗thx你的responde但它不適合我。我嘗試「awk」/^#/{k=$0;next}/./{a[k][$1]=$0}END{for(k in a){print k; for(i in a [k] )print a [k] [i]}}'host_files.txt我有這個錯誤信息:語法錯誤上下文是: >>>/^#/ {k = $ 0; next} /./ {a [k] [ <<< –

+0

你有GNU awk嗎? –

+0

不,我沒有gnu awk –

1

這將在任何AWK工作:

$ cat tst.awk 
/^#/ { key = $0; next } 
NF && !seen[$0]++ { 
    ips[key] = ips[key] $0 ORS 
} 
END { 
    for (key in ips) { 
     print key ORS ips[key] 
    } 
} 

$ awk -f tst.awk file 
#apache 
12.56.35.36 #apachepub 
12.56.35.35 #apacheprivate 
12.56.35.37 #apachepub 

#ftp server IPs 
45.89.67.5 #ftpmain 
45.89.67.3 #ftpssh 
95.23.23.50 #ftp 

#backup server IPs 
95.23.23.56 #masterbasckup 
95.23.23.57 #agentbasckup 

輸出順序將是隨機的,由於使用in操作的,如果這是它的代碼來改變只是一對夫婦更多的線路有問題。

+1

這很好。 –

0

如果awk不是必需的。

#!/bin/ksh 

cat host_files.txt | while read line ; do 
    [[ $line =~ ^$ ]] && { continue; }    # skip empty lines 
    [[ $line =~ ^# ]] && { group=$line; continue; } # remember the group name 
    print "$group|$line"       # print with group name in front 
done | sort \ 
    | while read line ; do 
     if [[ ${line%\|*} != $last ]]; then   # if the group name changed 
      print "\n${line%\|*}"     # print the group name 
      last=${line%\|*}      # remember the new group name 
     fi 
     print "${line#*\|}"       # print the entry without the group name 
    done 
  • 把組名在該行的前
  • 排序
  • 檢測不斷變化的組名,並打印
  • 沒有組名
  • 打印入口

使用相同的概念用awk(避免shell中的while循環)。

awk ' 
    /^#/ { k=$0; next } 
    /./ { print k "|" $0 } 
' host_files.txt | sort | awk -F '|' '{ 
     if (k != $1) { print "\n" $1; k = $1; } 
     print $2 
    }' - 

因爲它不使用數組,所以不會因爲重複的鍵而鬆動線條。

而且,考慮更多一點,可以避免第二個awk。將密鑰添加到每一行。對於不帶'x'的標題。所以標題被排序在其餘的上面。在輸出中,只需刪除添加的排序鍵。

awk ' 
    /^#/ { k=$0; print k "|" $0; next; } 
    /./ { print k "x|" $0 } 
' t18.dat | sort -u | cut -d '|' -f 2 
+0

無論awk是否爲需求,它都是該工作的正確工具。請參閱[爲什麼要使用shell循環處理文本被認爲是不好的練習](https://unix.stackexchange.com/questions/169716/why-is-using-a-shell回到流程文本考慮糟糕的做法)爲什麼(以及谷歌UUOC)的一些原因。 –

+0

你對UUOC說得對。但它使數據流更加明顯(好吧,這不是最強的論據)。 – ULick

+0

只是想添加一種不同的方法,而不是將整個輸入讀入內存並在最後打印。但是兩個awk運行並且在中間可能是值得的。 – ULick

相關問題