1981 字
10 分钟
学习T神的《像黑客一样使用Linux命令行》

po主Linux/Unix奇菜无比,看到Toy大神的PPT《像黑客一样使用 Linux 命令行》画面太美,就必须学习一下。

依然是用OSX冒充Linux…

Talk is cheap…

1. 有趣的历史命令统计脚本#

用简单的几行命令找出shell执行过的历史命令中出镜率最高的10个:

Terminal window
~ history |
> awk '{CMD[$2]++;count++;}END \
> { for (a in CMD)print CMD[a] " " \
> CMD[a]/count*100 "% " a;}' |
> grep -v "./" |
> column -c3 -s " " -t |
> sort -nr |
> nl |
> head -n10
1 265 10.3962% git
2 258 10.1216% ls
3 205 8.04237% sudo
4 166 6.51236% man
5 164 6.4339% awk
6 118 4.62927% vi
7 92 3.60926% cd
8 80 3.13849% port
9 76 2.98156% cat
10 73 2.86387% ps
  • history其实是fc -l 1的别名,而fc命令可以用来列出编辑重新执行用户过去向Shell中输入的内容;
  • 再用awk过滤并统计history的结果:取history返回值的第二列(命令名称),存入名为CMD的映射并累加重复的命令,count负责统计总命令数,统计结束后按行输出<命令执行的次数、占总命令数的百分比、该命令的名称>;
  • 再用grep -v去除那些带有'/'的目录跳转(使用grep -vE "./| \."对po主有奇效,因为po主有时会使用类似.ssh的不规范写法进入一个目录);
  • 再用column命令造一个漂亮的表格;
  • 再用sort命令排序取逆;
  • 再用nl命令给结果加上序号;
  • 再用head命令取TOP10;

于是就漂亮的统计出了我的历史记录使用结果(看到mansudo的排名就知道应该是个noob)。

2. 有用的执行的命令的修改#

po主因为noob,不熟悉系统,经常在输入命令的时候出现typo…这也是没办法的事,如果重新键入,或是把历史记录掉出来再移动光标至输入错误处修改,就太麻烦了,还好shell可以帮我:

Terminal window
# 一删
~ finder ~ -iname "using-cli-like-a-hacker.md"
zsh: command not found: finder
~ ^er
~ find ~ -iname "using-cli-like-a-hacker.md"
/Users/zealot/blog/source/_posts/using-cli-like-a-hacker.md
# 二改
~ echo "the ordre is incorrect"
the ordre is incorrect
~ ^re^er
~ echo "the order is incorrect"
the order is incorrect
~ echo "there is a typo"
there is a typo
~ ^a^no
~ echo "there is no typo"
there is no typo
# 三全换
~ ln /opt/local/bin/hub /usr/bin/hub
ln: /opt/local/bin/hub: No such file or directory
~ ^hub^git^:G # zsh
# 或!:gs/hub/git
~ ln /opt/local/bin/git /usr/bin/git

Toy神的口诀是:

  • 一删(^er
  • 二改(^a^no
  • 三全换(^hub^git^:G!:gs/hub/git

3. 深入了解命令历史#

3.1 历史记录属性:#

Terminal window
# 历史记录的大小
~ echo $HISTSIZE
10000
# 历史记录保存的位置
~ echo $HISTFILE
/Users/zealot/.zsh_history
# bash
~ echo $HISTFILESIZE
10000
# zsh
~ echo $SAVEHIST
10000

3.2 查看历史记录:#

Terminal window
~ history | less
# 显示前五条
~ history 5
# 在历史记录中查找
history | grep string
  • 按下[ctrl-R],进入逆向搜索历史模式:
Terminal window
~ history | less
bck-i-search: history |
  • 按下[ctrl+P]访问前一条命令
  • 按下[ctrl+N]访问下一条命令

3.3 关于!的历史引用#

  • 使用!!执行上一条命令:

这个很常用,特别是在没有权限的时候配合sudo使用:

Terminal window
~ port -v selfupdate
...
failed: Permission denied
...
~ sudo !!
~ sudo port -v selfupdate
Password:
...
  • 使用!foo执行以foo开头的命令:
Terminal window
~ !port
~ port outdated
  • 使用!?foo执行包含foo的命令:
Terminal window
~ !?out
~ port outdated
  • 使用!n执行历史记录中第n个命令(可能会很早):
Terminal window
~ !9
~ pwd
  • 使用!-n执行倒数第n个命令(比较常用):
Terminal window
~ !-9
~ echo $HISTSIZE

注:!-1 == !!

  • 使用!#引用当前行
Terminal window
~ echo !#
~ echo echo

3.4 历史命令的Word选取#

历史命令Word选取图

  • 使用!$得到上一条命令的最后一个参数:
Terminal window
~ mkdir videos
~ cd !$
~ cd videos
videos

也可以通过快捷键[alt+.]获得。

注:OSX上需要设置在Terminal->Terminal->Preferences->Settings->Keyboard中设置“Use option as meta key”,在iTerm上通常设置“left option key as +Esc”。

  • 使用!^得到上一条命令的第一个参数:
Terminal window
~ ls /usr/share/doc /usr/share/man
/usr/share/doc:
...
/usr/share/man:
...
~ cd !^
~ cd /usr/share/doc
doc

也可以通过快捷键[Ctrl+Alt+Y]获得。(OSX上似乎不行…求指点)

* 使用!:n得到上一条命令第n个参数:

Terminal window
~ touch foo.txt bar.txt baz.txt
~ vim !:2
~ vim bar.txt
  • 使用!:x-y得到上一条命令从第x到第y的参数:
Terminal window
~ touch foo.txt bar.txt baz.txt
~ rm !:1-3
~ rm foo.txt bar.txt baz.txt
  • 使用!:n*得到上一条命令中从第n个参数开始到最后的参数:
Terminal window
~ cat /etc/resolv.conf /etc/hosts /etc/hostname
~ vim !:2*
~ vim /etc/hosts /etc/hostname
  • 使用!*得到上一条命令的所有参数:
Terminal window
~ ls src dst
~ cp -r !*
~ cp -r src dst

关于Word选取,需要记住的是:

  • n:第n个参数;
  • ^|$:第一个参数|最后一个参数;
  • n*:从第n个参数开始取到最后的参数;
  • x-y:从第x个参数开始取到第y个参数;

3.5 历史命令的修饰符#

  • 使用:h选取路径的开头部分:
Terminal window
~ ls /usr/share/doc/bash/bash.html
/usr/share/doc/bash/bash.html
~ ls !$:h
~ ls /usr/share/doc/bash

相当于使用dirname命令。

  • 使用:t选取路径的结尾部分:
Terminal window
~ wget http://nginx.org/download/nginx-1.7.2.tar.gz
...
~ tar zxvf !$:t
~ tar zxvf nginx-1.7.2.tar.gz

相当于使用basename命令。

  • 使用:r选取文件名:
Terminal window
~ wget http://nginx.org/download/nginx-1.7.2.zip
...
~ unzip nginx-1.7.2.zip
...
~ cd !$:r
~ cd nginx-1.7.2
  • 使用:e选取扩展名:
Terminal window
~ echo filname.extension
filname.extension
~ echo !$:e
~ echo extension
#bash
.extension
# zsh
extension
  • 使用!:p打印命令:
Terminal window
~ echo *
...
~ !:p
~ echo *
  • 使用:s做替换:
Terminal window
~ echo this that
this that
~ !:s/is/e
~ echo the that
  • 也就是前面提到的“二改”:

    Terminal window
    ~ echo this that
    this that
    ~ ^is^e
    ~ echo the that
  • 使用:g做全局操作:
Terminal window
~ echo abcd abef
abcd abef
~ !:gs/ab/cd
~ echo cdcd cdef
  • 也就是前面提到的“三全换”:

    Terminal window
    ~ echo abcd abef
    abcd abef
    ~ ^ab^cd^:G
    ~ echo cdcd cdef
  • 使用:u将命令改为大写(zsh):
Terminal window
~ echo $histfile
~ echo !$:u
~ echo $HISTFILE
/Users/zealot/.zsh_history
  • 使用:l将命令该为小写(zsh):
Terminal window
~ echo $HISTORY
~ echo !$:l
~ echo $history
...

关于修饰符,要记住的是:

  • h|t:选取路径的开头|结尾;
  • r|e:选取文件名|扩展名;
  • p:打印命令;
  • s:替换操作;
  • g:全局操作;
  • u|l:将参数改为大写|小写;

综上:

历史命令结构展开图

4. 常备锦囊,内藏妙计#

  • 使用alias -s定义后缀别名(zsh):
Terminal window
~ alias -s py=python3
~ test.py
python3 test.py
  • 使用 {} 构造字符串:
Terminal window
~ cp grade.txt{,.bak}
~ cp grade.txt grade.txt.bak
~
~ vim {a,b,c}file.c
~ vim afile.c bfile.c cfile.c
~
~ wget http://linuxtoy.org/img/{1..5}.jpg
1.jpg 2.jpg 3.jpg 4.jpg 5.jpg
~
~ echo {01..5}.txt
01.txt 02.txt 03.txt 04.txt 05.txt
~
~ echo 0{1..5}.txt
01.txt 02.txt 03.txt 04.txt 05.txt
~
~ echo {1..10..2}.txt
1.txt 3.txt 5.txt 7.txt 9.txt
~
~ echo {1..10..-2}.txt
9.txt 7.txt 5.txt 3.txt 1.txt
~
~ echo {9..1..-2}.txt
1.txt 3.txt 5.txt 7.txt 9.txt
~
~ mkdir -p 2014/{01..12}/{baby,photo}
  • 使用“或$()做命令替换:
Terminal window
~ echo $(date +'%Y%m%d')
20140707
~ echo `date +'%Y%m%d'`
20140707
  • 使用变量保存信息:
Terminal window
~ LOG=/var/log/emerge.log
~ head $LOG
~ grep -i compiling $LOG
  • 使用 for … in 重复执行命令:
Terminal window
~ figlet -f font-type-1 Linux # (1)
~ figlet -f font-type-2 Linux # (2)
~ figlet -f font-type-3 Linux # (3)
~ ...
~
~ cd /usr/share/figlet
~ for font in *.flf
for> do
for> echo $font
for> figlet -f $font Linux
for> done
...
~ for font in *.flf; do echo $font; figlet -f $font Linux; done
~
~ for dev in /dev/sd{a..d}
for> do
for> hdparm -t $dev
for> done

5. 其他#

5.1 重要原则#

  • Type less, accomplish more (少打多做);
  • DRY, don’t repeat yourself (不要重复你自己);
  • Care about your tool (关心你的工具);

5.2. 此外…#

  • Tab补全;
  • 使用通配符 (*, ?, [a-z], [0-9]);
  • 用快捷键编辑命令行;
  • 字符串处理;
  • 复合命令 (;, &&, ||);

5.3 扩展阅读:#

ps: 关于awk, sed, grep等复杂命令,以后再详解。

-EOF-

学习T神的《像黑客一样使用Linux命令行》
https://zlotus.github.io/2014/07/07/using-cli-like-a-hacker/
作者
Z
发布于
2014-07-07
许可协议
CC BY-NC-SA 4.0