从一条变态命令谈几个常见unix工具的用法。

发表于:2007-05-26来源:作者:点击数: 标签:
从一条变态命令谈几个常见 unix 工具的用法。 从一条变态命令谈几个常见unix工具的用法。FlyDragon http://www.cnfreeos.org 在开头之前,向大家介绍本书《 UNIX 和SHELL程序设计权威教程》,是一本国外计算机科学的经典教材,我从这里学到了不少有趣的东西
从一条变态命令谈几个常见unix工具的用法。

从一条变态命令谈几个常见unix工具的用法。 FlyDragon http://www.cnfreeos.org 在开头之前,向大家介绍本书《UNIX和SHELL程序设计权威教程》,是一本国外计算机科学的经典教材,我从这 里学到了不少有趣的东西,希望学习系统管理的朋友也看看。(非广告,只是我个人认为不错) 下面的命令不是最简单的方法,放在这里是为了向大家介绍几个常见的工具的一些用法。希望能 激起大家的灵感,想出更巧妙的方法来解决身边的问题,我不大懂shell说错的地方请大家不要吝惜砖头 酒瓶。 grep -v ^$ a.txt|awk '{print }'|cut -f1-3 -d . |sed 's/^.*$/route add \-net &\.0 192\.168\.0\.1/' |uniq 有这么样一个平板文件a.txt: 60.48.0.0 - 60.54.255.255 马来西亚 电信 60.160.0.0 - 60.160.223.255 云南省 电信 60.160.224.0 - 60.160.225.255 云南省 文山州电信 60.160.226.0 - 60.161.255.255 云南省 电信 60.162.0.0 - 60.162.0.255 浙江省台州市 路桥区电信ADSL 60.162.1.0 - 60.162.51.255 浙江省 电信 60.162.52.0 - 60.162.52.255 浙江省临海市 电信 60.162.53.0 - 60.162.79.255 浙江省 电信 60.162.80.0 - 60.162.91.255 浙江省台州市 (天台)电信 60.162.92.0 - 60.162.127.255 浙江省台州市 电信 60.162.128.0 - 60.163.0.255 浙江省 电信 60.163.1.0 - 60.163.1.255 浙江省嘉兴市 电信 60.163.2.0 - 60.163.4.255 浙江省 电信 60.163.5.0 - 60.163.5.255 浙江省嘉兴市 电信 60.163.6.0 - 60.163.13.255 浙江省 电信 61.128.252.77 - 61.128.252.77 重庆市永川 电信非住宅宽带用户 61.128.252.79 - 61.128.252.79 重庆市永川 电信非住宅宽带用户 61.128.252.83 - 61.128.252.83 重庆市永川 电信非住宅宽带用户 61.128.252.85 - 61.128.252.85 重庆市永川 电信非住宅宽带用户 61.128.252.92 - 61.128.252.92 重庆市永川 电信非住宅宽带用户 61.128.252.94 - 61.128.252.94 重庆市永川 电信非住宅宽带用户 61.128.252.96 - 61.128.252.96 重庆市永川 电信非住宅宽带用户 简单说明下,这个是freebsdchina论坛中热心网友share出来的一些地区的ip列表,好让大家做策略路由,根据目 标网络的服务商来选择路径,访问电信的ip走电信的线,访问网通的ip走网通的线。 上面的文件中的ip. 都是一些电信服务商的,也就是说希望把这些ip段做成n条静态路由,需要类似这样的命令来完成: route add -net 60.48.0.0 192.168.0.1 route add -net 60.160.224.0 192.168.0.1 ........ 下面我们一步步来看看那一长串命令都做了什么。 grep -v ^$ a.txt grep 是比较经典的命令之一,他表示“全局正则表达式打印(Global regular expression print),是一个程序家族, 它可以对输入文件中匹配指定正则表达式的所有行进行搜索,并把输出写到标准输出文件(显示器). (正则表达式格式参见man 7 re_format), 它的命令格式是: grep 选项 正则表达式 文件列表 常见的选项有下面几个: -i忽略大小写 -n打印行号 -v打印不匹配行(排除RE) -f file表达式在文件中 上面的命令,参数是 -v 正则表达式是 " ^$ " 也就是空行,通过这个命令我们就排除了中间的几个空行 。 |是一个管道操作符号,管道在UNIX系统里很常用,管道会将一个命令的输出保存到临时缓冲区,然后缓冲区的 内容被做为下一个命令的输入,管道有一个使用要求,就是前面的命令必须能发送输出到标准输出设备,后面 的命令必须能从标准输入设备读入需要的输入。由于种种特性,管道通常是避免创建中间文件的手段。 awk '{print }' awk名字来自它的创始人(Alfred V.Aho、Perter J.Weinberger和Brian W.Kernighan),相比其他工具来说它有 点强大过分了。没错,它本来就是一个伪装成使用程序的编程语言。awk和sed工作类似,它从输入文件中逐行 读入,并整行或部分执行一个动作。但和sed不同,除非你明确指定,awk不会打印行。 正如刚才所说,awk太强大了,包含了诸如数组,函数,流程等其他工具所不支持的特性,我们就不打算在 这里多说awk,学习awk有本不错的书籍OReilly的sed & awk.回过头来,刚才的命令是awk才shell程序里比较 典型的一个“列打印”,awk把文件看成字段和记录的集合,awk约定使用一个或多个空格或用户定义的其他字 符来分割字段,同时,awk把每行都看成一个记录,所以刚才的命令,替我们从上次的结果中抽取出第一列,ip 地址部分。 管道操作符继续把我们的输出定向到下面的输入。 cut -f1-3 -d . (注意后面有个点) cut是一个过滤器命令,它和paste属于一个类型的命令,cut从文件中删除列,paste连接列 它的命令格式是: cut 选项 文件列表 常见的选项有-c(指定字符位置),-f指定区域,-d重新定义分割符号,-s行内没有分割符的时候抑制输出。 经过2次的操作,我们的ip地址文件已经边的仅剩下一列了: 60.160.224.0 ... 60.163.2.0 ... 61.128.252.96 我们的cut命令,-d指定了用点做分割符,划分出一块块的区域来,同时我们用-f来指定输出区域1到3的内容。 也就是去掉了ip地址的最后面一段,我们这样做是为了把其中有些不是网络的ip转换成ip。其实这样已经够了 ,不做后面的sed操作也可以在路由中表示网络。但我们还是来个画蛇添足,借此熟悉下正则表达式的命令的: 保存、向后引用、重复、锚、点,缓冲区等知识,以及sed的基本替代,和原子替换操作。 正则表达式是UNIX比其他操作系统方便都理由之一,它太cool了,高效的表达字符串的方法,是高手为之骄傲 的本钱,乱遭遭的字符序列,却是让初学者和外行迷惑,甚至不寒而栗。熟悉并使用正则表达式,需要你做很 多的实践并要锻炼自己的小聪明和偷懒习惯。 由于篇幅有限,我们不深入讲解,未尽兴的地方请读者自己 man re_format. 我们从sed支持的正则表达式说起,sed支持正则表达式的字符、点、类、锚、序列、向后引用、重复和保存 单字符,点,类,锚和向后引用组成了正则表达式的原子,原子用来匹配文本的内容,并发现文本的位置。 字符,很容易理解,任何一个单字符就是一个最简单的RE,它匹配这个确定的字符。 点 ,就是一个英文标点的句号,他匹配除\n外的任何单字,它的范围这么大,以至于他自己本身并不能做什么 ,但当它和其他元素结合起来就可以发挥出强大的表达能力,大家不难理解a.b可以代替aab、abb,acb,a2b..... 类,定义了一个Ascii集合,只要集合中的一个元素匹配了文本,那么这块文本就满足了这个集合型的RE,就是 说[abc]这个集合包含a,b,c三者,三个字符都满足这个RE,类中,还有常见2个符号,一个是破折号“-”用来 表示连续空间,比如[a-z]、[A-Z]、[0-9]等,另一个是 非“ ^ ”用来表示余集 ,比如[^aeiou]表示任意非元 音字符 锚,一般用来做对齐用,只有4种锚 ^表示行首,$行尾,\<单词开头,\>单词结尾,注意,锚匹配的是对齐,也 就是不可见的,一般用来和其他原子联合使用 ,^A(以大写字母A开头),8$以数字8结尾,e\>以e结尾的单词 。 向后引用,可以把文本保存在9个缓冲区中,留做以后用,向后引用提供了取出缓冲区文本的方法。使用向后引 用之前需要先“保存”,一会我们要讲。向后引用使用转义字符\和1到9,这9个数字结合使用。比如表示 取出2号和3号缓冲区内容。 为了让RE更强大,可以把原子和运算符结合起来。正则表达式有序列、替换、重复、组、保存共5种运算符。 序列,是一个空运算符,表示在出现原子系列的地方,如字符序列abc、或a4s2,他们中间都隐含一个序列运算 符. 重复,是转移括号\的集合,它包含2个数字m和n,由逗号分开,m表示至少,n表示至多,当然也可以只 剩一个数字,或一个数字一个逗号,如\重复3次,\重复3到6次,\不少于3次,聪明的你可能 立即想到\表示最多4次,没错,就是这么简单。 保存,这个操作可以把文本放到9个缓冲区中,它的符号是\(...\)两个转义括号中间放置需要保存的内容,依 照顺序,第一个被保存的文本就会被放置到缓冲区1,依次类推。 为了简化RE ,有一些特殊形式的缩写运算符号,比如*匹配前面的原子一次或多次,?匹配前面的原子0次或1次 假设文件1.txt中有下面内容 1234567890 1234567890 那么下面这个长长的命令 sed 's/\([0-9]\\)\([0-9]\\)\([0-9]\\)/--/' 1.txt 会帮助你把它格式化成这个形式: 123-890-4567 123-890-4567 这个命令为我们展示了sed的一个替代命令s 的基本用法: s/模式/替换物/ 再看上面的命令 s/\([0-9]\\)\([0-9]\\)\([0-9]\\)/--/ 虽然很长,但根据我们刚才学过的知识,不难拆开它。 \([0-9]\\)\([0-9]\\)\([0-9]\\) 这个串表达了一个RE,并保存到了3个缓冲区里。 \([0-9]\\)描述了这样一个序列“精确重复3次的由0-9中之一字符,也就是一个3个数字组成的序列” 我们看后面的替换物,这个是由缓冲区取出并重新组成的串。 -- 由缓冲区1加个-然后紧跟缓冲区3再加-再跟缓冲区2,三个缓冲区重新组合后就是新的替换用序列。 我们回头在来看看我们开头所说的命令: sed 's/^.*$/route add \-net &\.0 192\.168\.0\.1/' 这个也是一个重新格式化,和替换的例子。&操作符号将代表前面的“模式”在这里代表 ^.*$也就是所有的行 。在替换物当中,一些特殊的字符,需要使用转义符号\来屏蔽原来的含义。 上面的命令以理解为:“在每一个ip地址开头加 "route add -net "然后紧跟这个ip地址,最后以192.168.0.1 结尾。于是就满足了 route add -net 60.48.0.0 192.168.0.1 route add -net 60.160.224.0 192.168.0.1 这样的命令格式 仔细看下下现在的输出,你可能发好多重复的行,这些是由一些固定的ip而非网络被过滤后的结果,我们可以 用uniq消除它,uniq也是一个过滤器,它删除重复的行。 终于敲完了,好累,希望能对大家有点用处。 本页使用vim编辑 另一种方法是可以用 pf 的 reply-to/route-to 配合 table 来做。

原文转自:http://www.ltesting.net