变量
每一个变量的值都是字符串
定义:tuyou='涂有';
等号两边不能有空格;双引号内可写变量,单引号不行;tuyou=$(ll)在内容中执行变量
清除:unset tuyou;
取值:$tuyou、${tuyou};
打印:echo $tuyou;
获取变量长度:${#var}
设为环境变量:export tuyou;
数值运算符
整数运算符:
let命令可以直接执行基本的算术操作。当使用let时,变量名之前不需要再添加$,如:
let result=no1+no2
操作符$[]的使用方法和let命令类似,如:
result=$[ no1 + no2 ]、result=$[ $no1 + 5 ]
也可以使用$(()),如:
result=$(( no1 + 50 ))
expr同样可以用于基本算术操作,如:
result=`expr 3 + 4`
result=$(expr $no1 + 5)
浮点运算符:
bc是一个用于数学运算的高级工具
乘法:echo "4*5.5" | bc
除法:echo "scale=2;10/3" | bc
数组
普通数组
创建:array_var=(1 2 3 4 5 6);
赋值:array_var[0]="test1"
获取值:echo ${array_var[0]}、echo ${array_var[$index]}
获取所有key:echo ${array_var[*]}、echo ${array_var[@]}
数组长度:echo ${#array_var[*]}
关联数组
创建:declare -A ass_array
赋值:
ass_array=([index1]=val1 [index2]=val2)
ass_array[index1]=val1
取值:${fruits_value[apple]}
获取所有key:echo ${!array_var[*]}、echo ${!array_var[@]
循环
while true
do
$@ && return
done
shell内建的“ :”命令,它总是会返回为0的退出码
repeat() { while :; do $@ && return; done }
data可以是字符串和序列
for item in $data;
do
echo Item: $item
done
C语言形式循环
for((i=0;i<10;i++))
{
commands; #使用变量$i
}
until循环
x=0;
until [ $x -eq 9 ]; #条件是[$x -eq 9 ]
do
let x++; echo $x;
done
分支
if condition; then
commands;
else if condition; then
commands;
else
commands;
fi
算术比较
条件通常被放置在封闭的中括号内。一定要注意在[或]与操作数之间有一个空格。如果忘记了这个空格,脚本就会报错。例如:
[$var -eq 0 ] or [ $var -eq 0]
对变量或值进行算术条件判断:
[ $var -eq 0 ] #当 $var 等于 0 时,返回真
[ $var -ne 0 ] #当 $var 为非 0 时,返回真
其他重要的操作符如下所示。
- -gt:大于。
- -lt:小于。
- -ge:大于或等于。
- -le:小于或等于。
可以按照下面的方法结合多个条件进行测试:
[ $var1 -ne 0 -a $var2 -gt 2 ] #使用逻辑与-a
[ $var1 -ne 0 -o var2 -gt 2 ] #逻辑或 -o
文件系统相关测试
我们可以使用不同的条件标志测试不同的文件系统相关的属性。
- [ -f $file_var ]:如果给定的变量包含正常的文件路径或文件名,则返回真。
- [ -x $var ]:如果给定的变量包含的文件可执行,则返回真。
- [ -d $var ]:如果给定的变量包含的是目录,则返回真。
- [ -e $var ]:如果给定的变量包含的文件存在,则返回真。
- [ -c $var ]:如果给定的变量包含的是一个字符设备文件的路径,则返回真。
- [ -b $var ]:如果给定的变量包含的是一个块设备文件的路径,则返回真。
- [ -w $var ]:如果给定的变量包含的文件可写,则返回真。
- [ -r $var ]:如果给定的变量包含的文件可读,则返回真。
- [ -L $var ]:如果给定的变量包含的是一个符号链接,则返回真。
使用方法如下:
fpath="/etc/passwd"
if [ -e $fpath ]; then
echo File exists;
else
echo Does not exist;
fi
字符串比较
使用字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误,所以最好避开它们。
可以用下面的方法检查两个字符串,看看它们是否相同。
- [[ $str1 = $str2 ]]:当str1等于str2时,返回真。也就是说, str1和str2包含
的文本是一模一样的。 - [[ $str1 == $str2 ]]:这是检查字符串是否相等的另一种写法。
也可以检查两个字符串是否不同。 - [[ $str1 != $str2 ]]:如果str1和str2不相同,则返回真。
我们还可以检查字符串的字母序情况,具体如下所示。 - [[ $str1 > $str2 ]]:如果str1的字母序比str2大,则返回真。
- [[ $str1 < $str2 ]]:如果str1的字母序比str2小,则返回真。
- [[ -z $str1 ]]:如果str1包含的是空字符串,则返回真。
- [[ -n $str1 ]]:如果str1包含的是非空字符串,则返回真。
注意在= 前后各有一个空格。如果忘记加空格,那就不是比较关系了,而变成了赋值语句。
使用逻辑运算符 && 和 || 能够很容易地将多个条件组合起来:
if [[ -n $str1 ]] && [[ -z $str2 ]] ;
then
commands;
fi
例如:
str1="Not empty "
str2=""
if [[ -n $str1 ]] && [[ -z $str2 ]];
then
echo str1 is nonempty and str2 is empty string.
fi
输出如下:
str1 is nonempty and str2 is empty string.
test命令可以用来执行条件检测。用test可以避免使用过多的括号。之前讲过的[]中的测
试条件同样可以用于test命令。
例如:
if [ $var -eq 0 ]; then echo "True"; fi
#也可以写成:
if test $var -eq 0 ; then echo "True"; fi
函数
- 定义函数:
function fname()
{
statements;
}
#或者:
fname() #推荐使用C语言风格,兼容性好,可以在csh/tsch中使用
{
statements;
}
- 只需要使用函数名就可以调用某个函数:
$ fname ; #执行函数
- 参数可以传递给函数,并由脚本进行访问:
fname arg1 arg2 ; #传递参数
以下是函数fname的定义。在函数fname中,包含了各种访问函数参数的方法。
fname()
{
echo $1, $2; #访问参数1和参数2
echo "$@";#以列表的方式一次性打印所有参数
echo "$*"; #类似于$@,但是参数被作为单个实体
return 0; #返回值
}
函数也能像环境变量一样用export导出:
export -f fname
调试
打印出所执行的每一行命令以及当前状态:
bash -x script.sh
对脚本进行部分调试:
set -x和set +x
重定向
- 0 —— stdin(标准输入)。
- 1 —— stdout(标准输出)。
- 2 —— stderr(标准错误)。
例如:
cmd 2>stderr.txt 1>stdout.txt
#或者
cmd &> output.txt
标准错误和标准输出都到一个文件
tee可以把输入流输出到文件,而且返回输出流,如:
cat a* | tee -a out.txt | cat -n
创建一个文件输入描述符
$ echo this is a test line > input.txt
$ exec 3<input.txt
$ cat<&3
创建一个文件输出描述符
$ exec 4>output.txt
$ echo newline >&4
$ cat output.txt
别名
设置:alias new_command='command sequence'
取消:unalias new_command
创建别名时,如果已经有同名的别名存在,那么原有的别名设置将被新的设置取代
执行原生命令:\command
,避免执行别名命令
管道与子Shell
- 先从组合两个命令开始:
例如:ls | cat -n > out.txt - 我们可以用下面的方法读取由管道相连的命令序列的输出:
cmd_output=$(COMMANDS)
这种方法被称为子shell。例如:
cmd_output=$(ls | cat -n)
echo $cmd_output
另一种被称为反引用(有些人们也称它为反标记)的方法也可以用于存储命令输出:
cmd_output=COMMANDS
例如:
cmd_output=`ls | cat -n`
echo $cmd_output
子shell本身就是独立的进程。可以使用()操作符来定义一个子shell:
pwd;
(cd /bin; ls);
pwd;
注意:当使用子shell赋值给一个变量时,返回的空格和换行将不再,可以使用双引号保留
$ cat text.txt
1
2
3
$ out=$(cat text.txt)
$ echo $out
1 2 3 # Lost \n spacing in 1,2,3
$ out="$(cat tex.txt)"
$ echo$out
1
2
3
命令行输入
- 下面的语句从输入中读取n个字符并存入变量variable_name:
read -n number_of_chars variable_name
例如:
$ read -n 2 var
$ echo $var
- 用无回显的方式读取密码:
read -s var
- 显示提示信息:
read -p "Enter input:" var
分隔符
分隔符就是IFS变量,默认是以空白字符为分隔符
设置分隔符:IFS="."
例如:
data="name,sex,rollno,location"
我们可以使用IFS读取变量中的每一个条目。
oldIFS=$IFS
IFS=,
for item in $data;
do
echo Item: $item
done
IFS=$oldIFS
其他
- root的$UID环境变量为0
- $?打印上一句语句返回值
- shell文件第一行:#! /bin/bash
- sleep seconds可以设置延时
- 退出:exit