#!/usr/bin/env bash
#----------------------
# 这里是注释
#----------------------
<<EOF
这里是多行注释
EOF
echo "hello, world"
# printf 后面的格式化字符串可以是加双引号,可以加单引号,可以不加引号
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
name="abc" # 定义变量,等号两边不能有空格
unset name # 注销变量
# 局部变量 - 局部变量是仅在某个脚本内部有效的变量。它们不能被其他的程序和脚本访问。
# 环境变量 - 环境变量是对当前shell会话内所有的程序或脚本都可见的变量。创建它们跟创建局部变量类似,但使用的是 export 关键字,shell 脚本也可以定义环境变量。
# 数据类型:整型 字符串 数组
# 单引号不识别变量,双引号识别变量
str1="abc"
str2="123"
echo "$str1""$str2"
# 获取字符串长度
echo "${#str1}"
# 获取子串长度,下标从0开始,最后一个参数截取字符串个数
str3="123456"
echo ${str3:1:3}
echo ${str3:1:1}
# 查找子字符串的位置
str4="123456aabcdef"
echo `expr index ${str4} aa`
# bsah只支持一维数组,下标必须大于等于0
arr1=("aa", "bb", "cc")
arr2=([2]=2 [0]=0 [1]=1)
echo ${arr1[0]}
echo ${arr1[1]}
echo ${arr1[*]} # 输出全部数组元素
echo ${arr1[@]} # 输出全部数组元素
echo ${#arr1[*]} # 访问数组长度
arr3=("11", ${arr1[*]}, "22") # 向数组中添加元素,实际上是创建一个新数组
echo ${arr3[*]}
unset arr2[2] # 删除数组中的元素
echo ${arr2[*]}
# 算术运算
<<EOF
运算符 说明 举例
+ 加法 expr $x + $y 结果为 30。
- 减法 expr $x - $y 结果为 -10。
* 乘法 expr $x * $y 结果为 200。
/ 除法 expr $y / $x 结果为 2。
% 取余 expr $y % $x 结果为 0。
= 赋值 x=$y 将把变量 y 的值赋给 x。
== 相等 用于比较两个数字,相同则返回 true。 [ $x == $y ] 返回 false。
!= 不相等 用于比较两个数字,不相同则返回 true。[ $x != $y ] 返回 true。
EOF
a=10
b=20
echo `expr $a + $b`
echo `expr $a - $b`
echo `expr $a / 3`
# 关系运算:关系运算符只支持数字,不支持字符串,除非字符串的值是数字
<<EOF
运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ]返回 false。
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ]返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ]返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ]返回 true。
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ]返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ]返回 true。
EOF
if [[ ${a} -eq ${b} ]]; then
echo "${a} -eq ${b} : a 等于 b"
else
echo "${a} -eq ${b}: a 不等于 b"
fi
# 布尔运算
<<EOF
运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
EOF
if [[ ${a} -eq ${b} && false ]]; then
echo "${a} -eq ${b} : a 等于 b"
else
echo "${a} -eq ${b}: a 不等于 b"
fi
# 字符串运算符
<<EOF
运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为 0,为 0 返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否为 0,不为 0 返回 true。 [ -n $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。
EOF
s="abcd"
if [[ -z $s ]]; then
echo "字符串是空"
else
echo "字符串不是空"
fi
# 文件测试运算符
<<EOF
操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
-d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ]返回 false。
-p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
-r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
-w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
-x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
-s file 检测文件是否为空(文件大小是否大于 0),不为空返回 true。 [ -s $file ] 返回 true。
-e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。
EOF
file="/etc/hosts"
if [[ -r ${file} ]]; then
echo "${file} 文件可读"
else
echo "${file} 文件不可读"
fi
echo "*********************************************************"
# 控制语句
x=1
y=2
if [[ $x > $y ]]; then
echo "x > y"
elif [[ $x < $y ]]; then
echo "x < y"
else
echo "x = y"
fi
operator="+"
case $operator in
"+")
echo `expr $x + $y`
;;
"-")
echo `expr $x - $y`
;;
"*")
echo `expr $x * $y`
;;
"/")
echo `expr $x / $y`
;;
*)
echo "default"
;;
esac
z=1.2
case $z in
1.2)
echo "two"
;;&
"1.2")
echo "one"
;;
*)
echo "default"
;;
esac
# )匹配case,;;表示break,*)表示匹配任意条件,也就是最后的default
# ;;& 后面的条件继续匹配,匹配的case会进入执行
# ;& 后面挨着的一个case无条件执行,直到break跳出
# 循环语句
for x in 2 3 4 5 6
do
echo $x
done
data=(8 9 10)
for x in ${data[*]}
do
echo $x
done
for (( i = 0; i < 10; i++ )); do
echo $i
done
for path in /home/chusiyong/*
do
echo $path
done
x=0
while [[ ${x} -lt 10 ]]
do
echo $((x * x))
x=$((x + 1))
done
x=0
until [[ ${x} -ge 5 ]]; do
echo ${x}
x=`expr ${x} + 1`
done
# 函数
<<EOF
[ function ] funname [()] {
action;
[return int;]
}
函数定义时,function关键字可有可无。
函数返回值,return返回函数返回值,返回值类型只能为整数(0-255)。如果不加return语句,shell默认将以最后一条命令的运行结果,作为函数返回值。
函数返回值在调用该函数后通过 $?来获得。
所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时才可以使用。调用函数仅使用其函数名即可
函数内部获取参数
变量 描述
$0 脚本名称
$1 … $9 第 1 个到第 9 个参数列表
${10} … ${N} 第 10 个到 N 个参数列表
$* or $@ 除了$0外的所有位置参数
$# 不包括$0在内的位置参数的个数
$FUNCNAME 函数名称(仅在函数内部有值)
函数调用
funname arg1 arg2 ...
EOF
func ()
{
echo "$1"
echo "$2"
echo "$#"
}
func "one" "two"
# shell扩展
# 大括号扩展
echo {0..10}
echo {0..10..2}
# 命令置换
now=`date +%T`
echo $now
# 单引号和双引号之间有很重要的区别。在双引号中,变量引用或者命令置换是会被展开的。在单引号中是不会。
INPUT="A string with strange whitespace."
echo $INPUT
echo "$INPUT"
# 重定向
<<EOF
代码 描述符 描述
0 stdin 标准输入
1 stdout 标准输出
2 stderr 标准错误输出
EOF
# command > /dev/null 2>&1 标准输出和标准错误都输出到/dev/null
# command > /dev/null 2>1 标准错误输出到文件名是"1"的文件
标签: echo, Shell, case, expr, 语法, do, done