bash编程备忘
1 | bash -n test.sh # 检测语法 |
说明
若从技术的细节来看,shell会依据IFS(Internal Field Seperator) 将命令行所输入的文字拆解为”字段”(word/field)。 然后再针对特殊字符(meta)先作处理,最后重组整行命令行
IFS
:有space
或者tab
或者Enter
三者之一组成(我们常用space)CR
: 由Enter
产生;
IFS
(Internal Field Seperator)是用来拆解command line
中每一个词(word)用的,因为shell command line
是按词来处理的。
而CR
则是用来结束command line
用的,这也是为何我们敲Enter
键,命令就会跑的原因。
除了常用的IFS
与CR
, 常用的meta还有:
meta字符 | meta字符作用 |
---|---|
= | 设定变量 |
$ | 作变量或运算替换(请不要与shell prompt 混淆) |
> | 输出重定向(重定向stdout) |
< | 输入重定向(重定向stdin) |
& | 重定向file descriptor或将命令至于后台(bg)运行 |
() | 将其内部的命令置于nested subshell执行,或用于运算或变量替换 |
{} | 将期内的命令置于non-named function中执行,或用在变量替换的界定范围 |
; | 在前一个命令执行结束时,而忽略其返回值,继续执行下一个命令 |
&& | 在前一个命令执行结束时,若返回值为true,继续执行下一个命令 |
! | 执行histroy列表中的命令 |
… | … |
变量
命名规则
- 等号左右两边不能使用分隔符号(IFS),也应避免使用shell的保留元字符(meta charactor)
- 变量的名称(name)不能使用$符号
- 变量的名称(name)的首字符不能是数字(number)
- 变量的名称(name)的长度不可超过256个字符
- 变量的名称(name)及变量的值的大小写是有区别的、敏感的(case sensitive,)
特殊变量
1 | $0 : 当前脚本的文件名 |
$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号包含时,都以”$1” “$2” … 的形式输出所有参数,但是当它们被双引号包含时,”$*“ 会将所有的参数作为一个整体,以”$1 $2 …”的形式输出所有参数;”$@” 会将各个参数分开,以”$1” “$2” … 的形式输出所有参数
字符串操作
1 | ${#str} : str的长度 |
1 | str='/var/log/messages' |
变量赋值
1 | ${arg:-word} :假如arg为unset或者null,输出word的值但不赋值 |
表达式
算术运算
1 | a=11;b=22 |
测试表达式
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
:推荐使用
-eq
:等于,-ne
:不等于,-qt
:大于,-qe
:大等于,-lt
:小于,-le
:小等于==
,<
,>
,!=
,=~
:左侧字符能否被右侧规则匹配-z $str
: 为空则为真-n $str
: 不空则为真-d file
: 是否是目录-e file
: 存在为真-f file
: 普通文件,-c
:字符设备,-p
:管道,-h
或-L
:符号链接,-S
:套接字&&
,||
,!
: [ -d /aa ] && [ -f f2 ]-a
,-o
,!
: [ -d /aa -a -f f2 ],[ ! -e /dd ]
1 |
判断
- if…fi
- if…else…fi
- if…elif…else…fi
- case…esac
循环
- for
- while
- until
函数
易错
- echo
1 | a="this *.txt" |
- cat
1 | cat <<EOF |
- .exp1.&&.cmd1.||.cmd2.
1 | # 由于i++返回值为1(假),所以i--也会执行 |
- for arg in $*
1 | # 正确写法 |
- [[ -e file ]]
1 | 如果file是链接文件,但指向的原文件不存在时,-e的结果为1(假),如果只想判断是否存在,如下: |
- for循环读文件不靠谱
1 | # 建议使用while |
简洁
- 位置参数
1 | arg=${1:-123} # 当$1不存在时,arg=123 |
- 格式化数字
1 | printf "%'.2f" 1234455.2323 # 1,234,455.23 |
- here document(cat <EOF)
1 | while read line; do |
- 多线程
1 | # 1. 使用(CMD)方式fork一个子进程来执行 |
1 | # 2. 使用文件描述符及管道方式的多进程 |
- vim编辑远程文件
1 | vim scp://data01.com//tmp/test.sh |
- 编辑当前命令
1 | # 遇到输入比较长的命令时,需要修改时,使用 ctrl+x ctrl+e,默认使用emacs,使用vim修改~/.bashrc |
参考
- shell 13问
- bash 编程易犯的错误