变量命名
规则
- 首字符必须为字母
- 中间不能有空格, 可以有下划线_
- 不能使用标点符号
- 不能使用bash里的关键字
代码风格建议
变量赋值
变量名=值, (注意, = 两边不能有空格)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var=1 var=$var+1 echo $var+1
let "var+=1"
echo $var 或者 var=1 var= expr $var + 1
let表示数学运算, expr用于整数值运算, 每一项用空格隔开, $[]将中括号内的表达式作为数学运算先计算结果再输出. 在bash中, 将数学运算结果赋给某个变量, var=$[ operation ]
变量自增, 自减 let var++ let var-- let var+=2
echo "10.2-2" | bc -- 小数运算要用bc $[]不支持小数
|
变量使用
$var ${var}
双引号“ “ 中可以用$var
单引号‘ ‘ 中不可以用$var
$(cmd) 与 `cmd` 等效, 推荐用前者
- 支持内嵌
- 不用转义
- 有些字体, 反引号和单引号很像, 让人看着很难受
内建变量
1 2 3 4 5 6 7
| - $RANDOM 随机数 - 字段分隔符, IFS=$'n' - $0 程序名, $1 … $9 是命令行参数, 多于9个命令行参数的话, 后面的需要${10} ${11}这种格式 - $# 表示传入的命令行参数的个数. 在{}中使用$#时, 要改用${!#}. - $* 所有命令行参数当成一个单词存储 - $@ 所有命令行参数当成一个字符串中的多个单词 - $$ 脚本的PID
|
比较运算符
文件比较运算符
1 2 3 4 5 6 7 8 9 10
| -e filename 如果 filename 存在, 则为真 [ -e /var/log/syslog ] -d filename 如果 filename 为目录, 则为真 [ -d /tmp/mydir ] -f filename 如果 filename 为常规文件, 则为真 [ -f /usr/bin/grep ] -L filename 如果 filename 为符号链接, 则为真 [ -L /usr/bin/grep ] -r filename 如果 filename 可读, 则为真 [ -r /var/log/syslog ] -w filename 如果 filename 可写, 则为真 [ -w /var/mytmp.txt ] -x filename 如果 filename 可执行, 则为真 [ -L /usr/bin/grep ] ! -e filename 如果 filename 不存在, 则为真 [ ! -e /var/log/syslog ] filename1 -nt filename2 如果 filename1 比 filename2 新, 则为真 [ /tmp/install/etc/services -nt /etc/services ] filename1 -ot filename2 如果 filename1 比 filename2 旧, 则为真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]
|
字符串比较运算符 (请注意引号的使用, 这是防止空格扰乱代码的好方法)
1 2 3 4
| -z string 如果 string 长度为零, 则为真 [ -z "$myvar" ] -n string 如果 string 长度非零, 则为真 [ -n "$myvar" ] string1 = string2 如果 string1 与 string2 相同, 则为真 [ "$myvar" = "one two three" ] string1 != string2 如果 string1 与 string2 不同, 则为真 [ "$myvar" != "one two three" ]
|
算术比较运算符
1 2 3 4 5 6
| num1 -eq num2 等于 [ 3 -eq $mynum ] num1 -ne num2 不等于 [ 3 -ne $mynum ] num1 -lt num2 小于 [ 3 -lt $mynum ] num1 -le num2 小于或等于 [ 3 -le $mynum ] num1 -gt num2 大于 [ 3 -gt $mynum ] num1 -ge num2 大于或等于 [ 3 -ge $mynum ]
|
结构语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| if command then commands fi
if command1 && command2 then commands fi
if command; then commands fi
if command then commands else commands fi
if command1 then commands elif command2 then commands fi
if test condition if [ condition ] 注意[]与condition之间的空格, > < 需要转义 then commands fi
if ((expression)) > < 不需要转义 then commands fi
if [[ condition ]] 可以用正则表达式 then commands fi
t="abc123"
[[ "$t" == abc* ]] [[ "$t" == "abc*" ]] [[ "$t" =~ [abc]+[123]+ ]] [[ "$t" =~ "abc*" ]]
case variable in pattern1 | pattern2) commands1 ;; pattern3) commands2:: ;; *) default commands ;; esac
for var in list do commands done
while test command do other commands done
until test command do other commands done
break n (default 1) 跳出n层循环 continue n (default 1) 继续n级循环
select var in list do commands done
|
函数
语法
1 2 3 4 5
| [ function ] funname [()] { action; [return int;] }
|
说明:
- 可以带function fun() 定义, 也可以直接fun() 定义, 不带任何参数.
- 参数返回, 可以显式return返回, return后跟数值n(0-255);如果不加, 将以最后一条命令运行结果, 作为返回值.
1 2 3 4 5 6 7 8 9 10 11
|
err() { echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $@" >&2 }
if ! do_something; then err "Unable to do_something" exit "${E_DID_NOTHING}” fi
|
注意事项
- 必须在调用函数地方之前, 声明函数, shell脚本是逐行运行. 不会像其它语言一样先预编译. 一次必须在使用函数前先声明函数.
- total=$(func 3 2);
- 函数返回值, 只能通过$? 系统变量获得, 直接通过=获得是空值
- 如果需要传出其它类型函数值, 可以在函数调用之前, 定义变量(这个就是全局变量). 在函数内部就可以直接修改, 然后在执行函数就可以读出修改过的值
- 如果需要定义自己变量, 可以在函数中定义, local 变量=值, 这时变量就是内部变量, 它的修改, 不会影响函数外部相同变量的值.
实用技巧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #! /bin/bash
set -o nounset
set -o errexit
log() { local prefix="[$(date +%Y/%m/%d\ %H:%M:%S)]:" if [[ "$_DEBUG" == "true" ]]; then echo "${prefix} $@" >&2 fi }
log "INFO" "a message"
|