$ ifconfig | grep -oP '(?<=addr:).*(?= Bcast)' 10.0.0.1
用到正则中的环视,比起管道接管道,简洁多了
[回复]
#!/bin/bash set -eEu set -o pipefail trap 'echo >&2 "$0: unknown error ($?)"' ERR PS4='+${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x
一段漂亮的调试用代码,特别是PS4的设置,让set -x 更加直观 摘自: http://paste.debian.net/104933/
$ stat --printf="%s\n" testfile 12
查看文件大小,比ls之流要方便得多,适合套用在脚本做计算
igi@gentoo ~/test $ cat a 3 4 5 5 6 5 7 7 8 8 igi@gentoo ~/test $ awk '!a[$0]++' a 3 4 5 6 7 8
利用awk的模式巧妙排重,相当的简洁好用
$ cat a 1 2 3 4 5 $ truncate -s `expr $(stat --printf="%s" a) - $(tail -n1 a|wc -c)` a $ cat a 1 2 3 4
删除文件最后一行,跨越文件系统,效率高,适合对大文件的操作
igi@gentoo ~/test $ file='/home/igi/test/a'; echo ${file##*/} a igi@gentoo ~/test $ file='/home/igi/test/a'; echo ${file%/*} /home/igi/test
使用shell的字符串截取,效率比basename、dirname之类的更高
igi@gentoo ~/test $ cat a 1 2 3 4 igi@gentoo ~/test $ awk 'i=!i' a 1 3
awk打印奇数行,同样利用模式开关, 也许有点难以理解,那看看下面这个
igi@gentoo ~/test $ cat a 1 2 3 4 igi@gentoo ~/test $ awk 'NR%2' a 1 3
或许你会想知道,如果打印偶数行怎么改?其实很简单,取非就可以了, 注意括号哦
igi@gentoo ~/test $ cat a 1 2 3 4 igi@gentoo ~/test $ awk '!(i=!i)' a 2 4 igi@gentoo ~/test $ awk '!(NR%2)' a 2 4
统计Tcp连接各种状态数,也许下面是你用过的
$ netstat -tn | tail -n+3 | awk '{print $NF}' | sort | uniq -c
tail -n+3只为了排除netstat输出的头两行, 或者你用过
$ netstat -tn | awk 'NR>2{print $NF}' | sort | uniq -c
同样时管道工,只不过利用awk排除了前两行 以上两种方法固然能完成工作,但效率实在不怎么样,一个是管道新开的子进程影响了效率,另一个则是排序影响了效率。其实awk可以漂亮的完成它
$ netstat -tn | awk 'NR>2{a[$NF]++}END{for(i in a)print i,a[$NF]}'
效率上比前面两种高很多哦,不信你自己测试下 当然,如果你只需要ESTABLISHED状态的数量,下面有个更好的
$ netstat -s | grep 'established' # 也许你需要root权限才能运行
有时候,你需要判断某一年是否是闰年,自己去计算固然可以,如果用shell的话,看看一个偷懒的方法
igi@gentoo ~ $ date -d '2012-02-29' >&/dev/null && echo '闰年' || echo '平年' 闰年
只要把2012改成自己需要的年份就可以了,当然用个变量去替换最好了 这个方法也不是没有缺点的,date命令可以指定的年份范围有限制,64位的系统比32位的范围宽许多。不过没找到相关说明,估计得看源代码了,有兴趣的自己看吧
在IRC里遇到一个比较特别的sed问题。 如果所匹配的行存在,则把它替换为’string’,如果不存在则插入’string’到最后一行. 这种问题,awk确实做起来比sed简单多,但sed也不是做不到
igi$ echo 'test' | sed -n '/test/{h;s//string/g};p;${x;s/^$/string/p}' string igi$ echo 'haha' | sed -n '/test/{h;s//string/g};p;${x;s/^$/string/p}' haha string
awk如何处理所匹配行后面某一行? 以打印匹配行的后面第3行为例
igi@gentoo ~ $ seq 10 | awk '/4/{f=4}--f==0' 7
看不明白?下面这个罗嗦版本应该容易理解
igi@gentoo ~ $ seq 10 | awk '/4/{f=4};--f==0{print}' 7
再加个exit,效率更高哦
igi@gentoo ~ $ time seq 20000 | awk '/^4$/{f=4}--f==0' 7 real 0m0.020s user 0m0.034s sys 0m0.002s igi@gentoo ~ $ time seq 20000 | awk '/^4$/{f=4}--f==0{print;exit}' 7 real 0m0.002s user 0m0.001s sys 0m0.002s
看出速度上的区别吧?
打印匹配行和其后面的100行
#GNU grep grep -A100 string #GNU sed sed -n '/string/,+100p' #awk awk '/string/{f=100}--f>=0'
GNU的工具,功能上还是挺强大的,这让那些用Unix的人郁闷了吧。
恩,都很经典啊~ 收藏鸟~
igi 回复:二月 15th, 2011 at 22:56
都是平时用到的,想起来就顺手写上来
把某个目录下的文件追加到另一个目录中的同位置同名的文件 不想用for之类到循环,可以试下find
find /home/gg/2009/ -type f -printf "%P\n" \ | xargs -n 1 -i{} awk '{print >>"/home/hh/2009/{}";}' "/home/gg/2009/{}"
几个需要注意到地方 1. -printf “%P\n” : 这是打印除去搜索路径的‘路径+文件名’ 2. 不使用cat的原因,是因为cat {} >/xxx/{} 重定向部分会被shell提前解析导致出错,利用awk来避免这样的情况
根据掩码值计算掩码位
igi@gentoo ~/test $ echo '255.255.255.240' | \ awk -F. '{for(i=1;i<=NF;i++){if($i==0){printf("%d\n",a);next}; \ while(!($i%2)){res++;$i=rshift($i,1)};a+=(8-res);res=0;}print a}' 28
主要利用了gawk的rshift函数
sed的r命令可以在匹配行后插入指定文件的内容,但如果要在匹配行之前插入呢?得费点心思
igi@gentoo ~/test $ cat a 1 2 3 4 aaa bbb igi@gentoo ~/test $ cat b test hello igi@gentoo ~/test $ sed -n '1{h;n};/aaa/r b ;x;$G;p' a 1 2 3 4 test hello aaa bbb
yinyueme(SS) 回复:五月 13th, 2011 at 02:24
or:
sed ‘/aaa/{h;s/.*/cat b/e;G}’ a
igi 回复:五月 15th, 2011 at 15:40
嗯,利用gnu sed的这个功能,调用cat命令来完成,也是不错的方法。
去除空行,包含那些含有空格、tab的行
igi@gentoo ~/test $ cat -A aaa 1$ $ 2$ $ 3$ $ 4$ $ $ $ 5$ igi@gentoo ~/test $ sed '/^\s*$/d' aaa 1 2 3 4 5 igi@gentoo ~/test $ awk 'NF' aaa 1 2 3 4 5
awk那个很巧妙的应用了NF变量
获取当前的shell名称 常见的方法是
igi@gentoo /tmp $ echo $0 /bin/bash igi@gentoo /tmp $ echo $SHELL /bin/bash igi@gentoo /tmp $ dash $ echo $0 dash $
不过这个$0在脚本中可就不是当前shell的名字,而是脚本的名字
igi@gentoo /tmp $ cat test.sh #!/bin/dash echo $0 igi@gentoo /tmp $ ./test.sh ./test.sh igi@gentoo /tmp $ bash test.sh test.sh
下面介绍的方法可以通吃不同的情况
igi@gentoo /tmp $ ps -p $$ -o command= | awk '{print $1}' /bin/bash igi@gentoo /tmp $ cat test.sh #!/bin/dash ps -p $$ -o command= | awk '{print $1}' igi@gentoo /tmp $ ./test.sh /bin/dash igi@gentoo /tmp $ bash test.sh bash igi@gentoo /tmp $ dash test.sh dash igi@gentoo /tmp $ . test.sh /bin/bash
打印匹配字符串之间的所有行,如果包含匹配行,awk和sed做起来都很简单
igi@gentoo /tmp $ seq 10 | sed -n '/3/,/6/p' 3 4 5 6 igi@gentoo /tmp $ seq 10 | awk '/3/,/6/' 3 4 5 6 igi@gentoo /tmp $
但如果是不要匹配行呢? 其实也不难
igi@gentoo /tmp $ seq 10 | sed -n '/3/{:f;n;/6/q;p;bf}' 4 5 igi@gentoo /tmp $ seq 10 | awk '/3/{f=1;next};/6/{exit};f' 4 5 igi@gentoo /tmp $
当然以上只考虑了只存在唯一的匹配字符串的情况,如果不是唯一的,那么就要分情况来说了
昵称
邮箱
网址
注意 - 你可以用以下 HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
用到正则中的环视,比起管道接管道,简洁多了
[回复]
#!/bin/bash set -eEu set -o pipefail trap 'echo >&2 "$0: unknown error ($?)"' ERR PS4='+${BASH_SOURCE}:${LINENO}: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'; set -x一段漂亮的调试用代码,特别是PS4的设置,让set -x 更加直观
摘自: http://paste.debian.net/104933/
[回复]
查看文件大小,比ls之流要方便得多,适合套用在脚本做计算
[回复]
利用awk的模式巧妙排重,相当的简洁好用
[回复]
删除文件最后一行,跨越文件系统,效率高,适合对大文件的操作
[回复]
igi@gentoo ~/test $ file='/home/igi/test/a'; echo ${file##*/} a igi@gentoo ~/test $ file='/home/igi/test/a'; echo ${file%/*} /home/igi/test使用shell的字符串截取,效率比basename、dirname之类的更高
[回复]
awk打印奇数行,同样利用模式开关, 也许有点难以理解,那看看下面这个
或许你会想知道,如果打印偶数行怎么改?其实很简单,取非就可以了, 注意括号哦
[回复]
统计Tcp连接各种状态数,也许下面是你用过的
$ netstat -tn | tail -n+3 | awk '{print $NF}' | sort | uniq -ctail -n+3只为了排除netstat输出的头两行, 或者你用过
$ netstat -tn | awk 'NR>2{print $NF}' | sort | uniq -c同样时管道工,只不过利用awk排除了前两行
以上两种方法固然能完成工作,但效率实在不怎么样,一个是管道新开的子进程影响了效率,另一个则是排序影响了效率。其实awk可以漂亮的完成它
$ netstat -tn | awk 'NR>2{a[$NF]++}END{for(i in a)print i,a[$NF]}'效率上比前面两种高很多哦,不信你自己测试下
当然,如果你只需要ESTABLISHED状态的数量,下面有个更好的
[回复]
有时候,你需要判断某一年是否是闰年,自己去计算固然可以,如果用shell的话,看看一个偷懒的方法
只要把2012改成自己需要的年份就可以了,当然用个变量去替换最好了
这个方法也不是没有缺点的,date命令可以指定的年份范围有限制,64位的系统比32位的范围宽许多。不过没找到相关说明,估计得看源代码了,有兴趣的自己看吧
[回复]
在IRC里遇到一个比较特别的sed问题。
如果所匹配的行存在,则把它替换为’string’,如果不存在则插入’string’到最后一行.
这种问题,awk确实做起来比sed简单多,但sed也不是做不到
igi$ echo 'test' | sed -n '/test/{h;s//string/g};p;${x;s/^$/string/p}' string igi$ echo 'haha' | sed -n '/test/{h;s//string/g};p;${x;s/^$/string/p}' haha string[回复]
awk如何处理所匹配行后面某一行? 以打印匹配行的后面第3行为例
igi@gentoo ~ $ seq 10 | awk '/4/{f=4}--f==0' 7看不明白?下面这个罗嗦版本应该容易理解
igi@gentoo ~ $ seq 10 | awk '/4/{f=4};--f==0{print}' 7再加个exit,效率更高哦
igi@gentoo ~ $ time seq 20000 | awk '/^4$/{f=4}--f==0' 7 real 0m0.020s user 0m0.034s sys 0m0.002s igi@gentoo ~ $ time seq 20000 | awk '/^4$/{f=4}--f==0{print;exit}' 7 real 0m0.002s user 0m0.001s sys 0m0.002s看出速度上的区别吧?
[回复]
打印匹配行和其后面的100行
#GNU grep grep -A100 string #GNU sed sed -n '/string/,+100p' #awk awk '/string/{f=100}--f>=0'GNU的工具,功能上还是挺强大的,这让那些用Unix的人郁闷了吧。
[回复]
恩,都很经典啊~ 收藏鸟~
[回复]
igi 回复:
二月 15th, 2011 at 22:56
都是平时用到的,想起来就顺手写上来
[回复]
把某个目录下的文件追加到另一个目录中的同位置同名的文件
不想用for之类到循环,可以试下find
find /home/gg/2009/ -type f -printf "%P\n" \ | xargs -n 1 -i{} awk '{print >>"/home/hh/2009/{}";}' "/home/gg/2009/{}"几个需要注意到地方
1. -printf “%P\n” : 这是打印除去搜索路径的‘路径+文件名’
2. 不使用cat的原因,是因为cat {} >/xxx/{} 重定向部分会被shell提前解析导致出错,利用awk来避免这样的情况
[回复]
根据掩码值计算掩码位
igi@gentoo ~/test $ echo '255.255.255.240' | \ awk -F. '{for(i=1;i<=NF;i++){if($i==0){printf("%d\n",a);next}; \ while(!($i%2)){res++;$i=rshift($i,1)};a+=(8-res);res=0;}print a}' 28主要利用了gawk的rshift函数
[回复]
sed的r命令可以在匹配行后插入指定文件的内容,但如果要在匹配行之前插入呢?得费点心思
igi@gentoo ~/test $ cat a 1 2 3 4 aaa bbb igi@gentoo ~/test $ cat b test hello igi@gentoo ~/test $ sed -n '1{h;n};/aaa/r b ;x;$G;p' a 1 2 3 4 test hello aaa bbb[回复]
yinyueme(SS) 回复:
五月 13th, 2011 at 02:24
or:
sed ‘/aaa/{h;s/.*/cat b/e;G}’ a
[回复]
igi 回复:
五月 15th, 2011 at 15:40
嗯,利用gnu sed的这个功能,调用cat命令来完成,也是不错的方法。
[回复]
去除空行,包含那些含有空格、tab的行
igi@gentoo ~/test $ cat -A aaa 1$ $ 2$ $ 3$ $ 4$ $ $ $ 5$ igi@gentoo ~/test $ sed '/^\s*$/d' aaa 1 2 3 4 5 igi@gentoo ~/test $ awk 'NF' aaa 1 2 3 4 5awk那个很巧妙的应用了NF变量
[回复]
获取当前的shell名称
常见的方法是
不过这个$0在脚本中可就不是当前shell的名字,而是脚本的名字
下面介绍的方法可以通吃不同的情况
igi@gentoo /tmp $ ps -p $$ -o command= | awk '{print $1}' /bin/bash igi@gentoo /tmp $ cat test.sh #!/bin/dash ps -p $$ -o command= | awk '{print $1}' igi@gentoo /tmp $ ./test.sh /bin/dash igi@gentoo /tmp $ bash test.sh bash igi@gentoo /tmp $ dash test.sh dash igi@gentoo /tmp $ . test.sh /bin/bash[回复]
打印匹配字符串之间的所有行,如果包含匹配行,awk和sed做起来都很简单
但如果是不要匹配行呢? 其实也不难
igi@gentoo /tmp $ seq 10 | sed -n '/3/{:f;n;/6/q;p;bf}' 4 5 igi@gentoo /tmp $ seq 10 | awk '/3/{f=1;next};/6/{exit};f' 4 5 igi@gentoo /tmp $当然以上只考虑了只存在唯一的匹配字符串的情况,如果不是唯一的,那么就要分情况来说了
[回复]