有趣的命令

发表评论?

22 条评论。

  1. igi
    $ ifconfig | grep -oP '(?<=addr:).*(?= Bcast)'
    10.0.0.1
    

    用到正则中的环视,比起管道接管道,简洁多了

    [回复]

  2. igi
    #!/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/

    [回复]

  3. igi
    $ stat --printf="%s\n" testfile
    12
    

    查看文件大小,比ls之流要方便得多,适合套用在脚本做计算

    [回复]

  4. igi
    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的模式巧妙排重,相当的简洁好用

    [回复]

  5. igi
    $ 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
    

    删除文件最后一行,跨越文件系统,效率高,适合对大文件的操作

    [回复]

  6. igi
    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之类的更高

    [回复]

  7. igi
    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
    

    [回复]

  8. igi

    统计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权限才能运行
    

    [回复]

  9. igi

    有时候,你需要判断某一年是否是闰年,自己去计算固然可以,如果用shell的话,看看一个偷懒的方法

    igi@gentoo ~ $ date -d '2012-02-29' >&/dev/null && echo '闰年' || echo '平年'
    闰年
    

    只要把2012改成自己需要的年份就可以了,当然用个变量去替换最好了
    这个方法也不是没有缺点的,date命令可以指定的年份范围有限制,64位的系统比32位的范围宽许多。不过没找到相关说明,估计得看源代码了,有兴趣的自己看吧

    [回复]

  10. igi

    在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
    

    [回复]

  11. igi

    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
    

    看出速度上的区别吧?

    [回复]

  12. 打印匹配行和其后面的100行

    #GNU grep
    grep -A100 string
    
    #GNU sed
    sed -n '/string/,+100p'
    
    #awk
    awk '/string/{f=100}--f>=0'
    

    GNU的工具,功能上还是挺强大的,这让那些用Unix的人郁闷了吧。

    [回复]

  13. 恩,都很经典啊~ 收藏鸟~ :mrgreen:

    [回复]

    igi 回复:

    都是平时用到的,想起来就顺手写上来

    [回复]

  14. igi

    把某个目录下的文件追加到另一个目录中的同位置同名的文件
    不想用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来避免这样的情况

    [回复]

  15. igi

    根据掩码值计算掩码位

    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函数

    [回复]

  16. 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) 回复:

    or:

    sed ‘/aaa/{h;s/.*/cat b/e;G}’ a

    [回复]

    igi 回复:

    嗯,利用gnu sed的这个功能,调用cat命令来完成,也是不错的方法。

    [回复]

  17. igi

    去除空行,包含那些含有空格、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变量

    [回复]

  18. igi

    获取当前的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
    

    [回复]

  19. igi

    打印匹配字符串之间的所有行,如果包含匹配行,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>