Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sorting 主机文件为所有服务器创建唯一的文件_Sorting_Awk - Fatal编程技术网

Sorting 主机文件为所有服务器创建唯一的文件

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

我有很多主机文件。我从所有服务器收集它们,并将它们放在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 
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