Sorting 主机文件为所有服务器创建唯一的文件
我有很多主机文件。我从所有服务器收集它们,并将它们放在host_files.txt中,然后我必须为所有服务器创建一个hosts文件 我执行此命令以生成唯一的文件,但某些行共享相同的ip地址或主机名Sorting 主机文件为所有服务器创建唯一的文件,sorting,awk,Sorting,Awk,我有很多主机文件。我从所有服务器收集它们,并将它们放在host_files.txt中,然后我必须为所有服务器创建一个hosts文件 我执行此命令以生成唯一的文件,但某些行共享相同的ip地址或主机名 awk '!a[$0]++' host_files.txt 这是我的主机文件.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
awk '!a[$0]++' host_files.txt
这是我的主机文件.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
我需要没有ip地址的ip地址请帮帮我
提前感谢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
输出是随机顺序的,因为(a中的k),即注释组和组内的IP没有特定顺序。这将在任何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
由于在运算符中使用了
,输出顺序将是随机的,如果这是一个问题,则只需再更改几行代码。如果不需要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是可以避免的。向每行添加键。对于不带“x”的标题。因此,标题的排序高于其余部分。在输出中,只需删除添加的排序键
awk '
/^#/ { k=$0; print k "|" $0; next; }
/./ { print k "x|" $0 }
' t18.dat | sort -u | cut -d '|' -f 2
@詹姆斯·布朗谢谢你的回复,但对我不起作用。我尝试使用“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]你有GNU AWK吗?对不起,我必须退出一段时间。如果你使用NWK,试试@ EdMordon的解决方案。我的只在GNU AWK上工作。如果可能的话,考虑一下GWWK,它有一些不错的特性。因为你使用IP地址作为关键字,如果IP被提到两次,你可能会松口气。AWK是否是必需的?ent与否,这是一个适合这项工作的工具。请参阅了解其中的一些原因(以及谷歌UOOC)。您对UOOC的看法是正确的。但它使数据流更加明显(好吧,这不是最有力的论点)只是想添加一种不同的方法,而不是把整个输入端读入内存和打印。但是两个AWK的运行和中间的排序可能是值得的。@ ULICK对不起,脚本工作得很好,但是很多重复行是肯定的吗?删除重复可以通过添加代码> -U/CODE >来完成。那太好了。
awk '
/^#/ { k=$0; next }
/./ { print k "|" $0 }
' host_files.txt | sort | awk -F '|' '{
if ( k != $1 ) { print "\n" $1; k = $1; }
print $2
}' -
awk '
/^#/ { k=$0; print k "|" $0; next; }
/./ { print k "x|" $0 }
' t18.dat | sort -u | cut -d '|' -f 2