学习bash
工作8年,前6年基本是Windows环境下,也就是个鼠标党;两年前换工作开始用linux,也就开始了领略了命令行的强大,无论是直接在命令行组合命令,也还写几行简单的shell脚本,其能完成的功能往往令人难以置信。
- 关于命令行强大的一个例子:csdn泄露的10个最常用的密码 awk '{print $3}' www.csdn.net.sql |sort |uniq -c |sort -nr |head (陈硕同学写的)
- 关于脚本强大的一个例子:提高分布式环境中程序启动性能的一个方法
如果说我工作中第一次感觉“哇”是08年左右开始使用perl处理文本 - 发现脚本原来可以如此强大,自动化那么多工作;那么第二次就应当是使用bash - 原来不用写脚本也能如此强大。(尤其对原Windows下鼠标+菜单党来讲)
这两天比较系统的看了下bash reference manual,记录一下。
一、命令行交互
这里包括两个部分,一个是readline支持的命令行编辑功能,有不同的编辑style:emacs和vi模式:
- set -o emacs
- set -o vi
用vi模式的话,使用vi一些常用的命令,编辑起来自然方便,但是需要先escape一下进入操作模式。但是对于平时99%的工作,一些常用的快捷键已经足够满足了:
- C-a, C-e:移动到行首,行尾
- Alt->, Alt-<-:前移,后移一个单词 (最好自己定义成右alt,额,好像是我的右alt键坏掉了。。。)
- C-b, C-f:前移,后移一个字符
- C-l:清空屏幕
- C-w:删除前一个单词
- Alt-d:删除后一个单词
- C-d:删除当前字符
- C-y:粘贴前次删除内容
这些快快捷键是readline的默认定义,一般在/etc/inputrc可以找到系统全局定义,然后个人可以定义:~/.inputrc
另一部分是历史管理,下面是一些要点:
- 控制历史的一些变量:HISTSIZE,HISTFILE,HISTFILESIZE
- 设置HISTTIMEFORMAT='%F %T '在历史中显示命令运行时间
- C-r:查找历史并运行
- history expansion
- !! - 上一条命令
- !preceding - 上一条以preceding开始的命令
- !$ - 上一个命令的最后一个参数
- !n - 第n个命令
- !-n - 倒数第n个命令
二、语法
1. 五种quoting
- \A:转义,保持字符原意,如果在行末,则表示续行
- 'string':single quoted string,不进行转义,变量expansion
- “string”:double quoted string,进行转义,变量expansion
- $'string':访问一些特殊字符,如$'\a', $'\n'
- $"string":locale specific translation, translated according to the current locale
2. 注释
以#开头的行均为注释,除了第一行:
#!/bin/bash
3. 控制结构
- 简单命令:cmd
- pipeline: cmd1 | cmd2
- 命令序列:
- cmd1; cmd2: 顺序执行两条命令
- cmd1& cmd2:并行执行两条命令,其中cmd1在后台执行
- cmd1 && cmd2: 如果cmd1成功了,执行cmd2
- cmd1 || cmd2:如果cmd1失败了,执行cmd2
- 循环控制
- until test-commands; do consequent-commands; done
- while test-commands; do consequent-commands; done
- for name [ [in [words …] ] ; ] do commands; done
- for (( expr1 ; expr2 ; expr3 )) ; do commands ; done - 例子:for ((i=1; $i < 100; i++)); do echo $i; done
- 条件控制
- if
if的测试表达式有三种情况:-x表示文件或者变量测试;(==, !=, >, <)表示字符串测试;(-gt, -lt, -eq, -ne, -ge)等表示数字测试。
if后测试的表达式可以有三种:
- [[ expression ]]
- [ expression ]
- test expression
-
if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
- case
case word in [ [(] pattern [| pattern]…) command-list ;;]… esac echo -n "Enter the name of an animal: " read ANIMAL echo -n "The $ANIMAL has " case $ANIMAL in horse | dog | cat) echo -n "four";; man | kangaroo ) echo -n "two";; *) echo -n "an unknown number of";; esac echo " legs."
- select
select name [in words …]; do commands; done select fname in *; do echo you picked $fname \($REPLY\) break; done
- 命令组合
- 新起shell:( list )
- 当前shell:{ list; }
4. 函数
语法 name () compound-command [ redirections ] or function name [()] compound-command [ redirections ] 定义 function reverse() { echo $3-$2-$1 } 调用 echo `reverse hello world thanks`
5. 参数
参数有脚本的参数、函数的参数,都是用$1-$9等来访问, $0表示脚本或者函数名字,这些叫做positional parameters,还有一些特殊的参数:$*, $@, $#, $?, $-等等
6. Shell expansion
- brace expansion: echo a{b, c, d}e
- tilde expansion: cd ~; cd ~user/bin
- shell parameter expansion: ${parameter}, , ${parameter:-word}.${parameter:=word}
- command expansion: $(cmd) or `cmd`
- arithmetic expansion: $((1+2*6))
- word splitting
- filename expansion: *.txt
- quote removal
7. Redirection
- >: write stdout to file
- >>: append stdout to file
- &>: write stdout and stderr to file
- &>>: append stdout and stderr to file
- tee: ls | tee ls.txt
8. Variable & array
# variable x=5 echo $x #array: arr[0]=100 echo ${arr[0]} #associate array: declare -A map map[hello]=world echo ${map[hello]}
三、内建命令与变量
builtin的命令,用help就可以全部打出来, 然后逐个help就可以看到大致介绍。
有两个主要的设置命令:
- set
- shopt
控制bash的各种行为模式。
但有个eval命令我有点搞不清楚:
$ help eval
eval: eval [arg ...]
Execute arguments as a shell command.Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.Exit Status:
Returns exit status of command or success if command is null.
这个,与没有eval,直接run命令有什么区别呢?搜了一下,发现这么个例子:
for i in 2 3 4; do eval a$i=2 eval echo "\$a$i" done
动态组合变量名字并赋值,这个在shell里直接是做不到的。
另外,三类比较常用的命令:
- 别名:alias, unalias
- job控制:jobs, fg, bg, kill, C-z
- 目录管理:dirs, popd, pushd
内置的变量,主要用来控制行为,或者暴露信息,臂长常用的有PATH, PS1, PS2, PWD, HOSTNAME, HISTFILE, IFS, CDPATH(这个貌似可以好好利用一下)
四、常用非内建命令
这里指的是非bash内置命令,但是linux内置的,或者另外安装的一些常用命令,非常有效,这里列几个自己用的比较多的:
du
df
strace
lsof
ps aux
netstat
grep
find
wget
curl
tr
ssh
sort
uniq
awk
wccut
top
free
vim
p4
perl -pei