shell的实质是命令解析器,分为图形化界面shell和命令行shell
shell脚本文件实质是文本文件,其内容为命令的有序集合
shell文件的注释用#
vim 1.sh
#!/bin/bash 执行这个shell脚本的程序路径
一行要执行多条指令,可以用;把各指令隔开
chmod +x 1.sh
./1.sh
echo "123" 或 echo 123
shell变量,没有类型的概念,全部是字符串
A=value //定义一个变量A并初始化为value
B= //定义一个变量B并初始化为空
引用变量:
$A 或 ${A}
shell变量,有四种
(1)自定义的变量 如 DATE=`date`(``反撇号,引用里面那个命令的执行结果)
(2)位置变量(传递命令行参数和函数调用时传递参数)
$0 表示命令程序名
$1,$2,$3...$9 表示第一个到第九个参数的名字
$# 表示命令行参数的个数(不包含脚本名)
$@ 包含所有命令行参数 $@ <=> "$1" "$2" "$3" ...
$* 包含所有命令行参数 $* <=> "$1C$2C$3C..." C是IFS的第一个
字符,IFS:internal Field Separator(分隔符),
默认的分隔符是空格,tab,换行
$? 表示前一个命令的退出状态(返回值)
$$ 表示正在执行进程的ID号
(3)shell环境变量,多个程序或命令共享的变量。
export 查看环境变量
HOME: 用户主目录
PATH: 命令搜索路径
LD_LIBRARY_PATH: 动态库搜索路径
PWD: 当前路径
...
(4)特殊变量:有特殊含义的变量,如位置变量
$_: 之前命令的最后一个参数
注意:
(1)在脚本中设计的环境变量只在脚本及子脚本范围内有效,
要想其在外边环境中生效,则需要前面加source
eg: source 1.sh
(2)如何使脚本(程序)后台执行
a.脚本(程序)后面加&符号,但是终端退出了,该进程也会结束
eg: ./a.out &
b.如果想让终端退出后,进程仍在:
eg: nohup ./a.out &
shell程序的语句
(1)说明性语句(注释)
以#开头的行,就是注释行
(2)功能性语句
任意的操作系统命令(echo,ls,date),shell内部命令,自编程序
read:在shell表示从终端输入, read var1
标准输入(0)/标准输出(1)/标准输错(2) ==> 重定向
1,输出重定向
命令的输出结果通常提交的到标准输出设备(终端),但也可以
很方便的转向到一个文件来代替,这叫做输出重定向。
在命令后添加 > filename,该命令(脚本)的输出就会写入到
filenmae这个文件中,而不是写入终端
>>filename 输出重定向,但是是追尾的方式
>filename 先清空filename,然后再输出重定向
echo "hello" > 1.txt
cat 1.txt >> 2.txt
2,输入重定向
命令的输入通常向校准输入设备请求的,但也可以很方便的转向一个
文件来代替,这叫输入重定向
命令 < filename 该命令所有的输入请求都来自filename
3,标准出错重定向
unix命令把大部分错误信息都写到这个设备里面。
一般情况下,标准出错设备和标准输出设备是同一个设备(默认为终端)
标准出错也可以重定向到文件
命令 2 > filename
命令 2 >> filename
expr: 算术运算命令,expr主要用于进行简单的整数计算,包括
加(+)、减(-)、乘(\*)、除(/)、取余(%)
expr 3 + 5 (注意:操作数与运算符,前后至少要有一个空格)
expr 12 + 5 \* 3 (且不支持括号)
eg: echo `expr 12 + 5 \* 3`
test: test语句可以测试三种对象:字符串,整数,文件属性
a.字符串测试
= 测试两个字符串内容是否完全一样
!= 测试两个字符串内容是否不一样
-Z (zero)测试字符串是否为空,为空,返回true
-n (null)测试字符串是否不为空,不为空,返回true
在测试字符串变量时,需要防止字符串为空的技巧:
引用变量后加一个额外的字符:
test ${A}x = ${B}x
b.整数测试
a -eq b : equal测试两个整数是否相等
a -ne b : non equal测试两个整数是否不相等
a -gt b : greater 测试a是否大于b
a -ge b : greater or equal 测试a是否大于等于b
a -lt b : little 测试a是否小于b
a -le b :little or equal 测试a是否小于等于b
c. 文件测试
-d name 测试name是否是一个目录(dir)
-f name 测试name是否是普通文件(file)
-L name 测试name是否为符号链接文件(Link)
-r name 测试name文件是否存在并可读(read)
-w name 测试name文件是否存在并可写(write)
-x name 测试name文件是否存在并可执行(excute)
-s name 测试name文件是否存在并且长度不为0(size)
f1 -nt f2 测试f1是否比f2更新(newer than)
f1 -ot f2 测试f1是否比f2更旧(older than)
test 命令可以用 [] 来简写
test expression <=> [ expression ]
test的复合表达式
组合了两个或两个以上的表达式称为复合表达式,你可以用
test([])内置的操作符,也可以用条件操作符(&&,||,!)来实现
a.使用test内置的操作符
test expr1 "test_buildin" expr2
test_buildin:
-a and
-o or
eg: test $A = '1' -a $B = '2'
b. 使用条件操作符(&&,||,!)
test expr1 "op" test expr2
eg: test $A = '1' && test $B = '1'
eg: [ $A = '1' ] && [ $B = '2' ]
(3)结构性语句(分支语句,循环语句)
a.条件语句
if command ; then
...语句列表
fi
if command ; then
...语句列表
else
...语句列表
fi
if command ; then
...语句列表
elif command ; then
...语句列表
else
...语句列表
fi
eg:
read var
if [ $var = "hello" ] ; then
echo "yes"
else
echo "no"
fi
b. 多路分支语句
case 字符串变量 in
模式1)
...语句列表
;; //作用类似与C语言的break,这里;;不能省
模式2)
....语句列表
;;
。。。
模式n)
....语句列表
;;
esac
eg:
read var
case $var in
"123")
echo "yes"
;;
"abc")
echo "no"
;;
esac
case语句真正的功能强大之处在于它可以使用模式而不是固定的字符串
匹配。一个模式是由一串正规字符和特殊的通配符组成的字符串
该模式可以用正则表达式。
c.循环语句
for 变量名 in 单词表
do
...语句列表
done
eg:
for var in a b c d e
do
echo $var
done
==>for也可以写成C风格相同的for循环
for(( i=1;i<100;i++ ))
do
...语句列表
done
//双圆括号(())使得shell程序中可以使用C语言的for风格
练习:写个脚本,求1到100的和
sum=0
for(( i=1;i<=100;i++ ))
do
sum=`expr $sum + $i`
done
echo "sum=$sum"
while 命令或表达式
do
...
done
==>也可以用c语言的while风格
while (( ))
do
...
done
练习:打印0到10
i=0;str=
while [ $i -le 10 ]
do
str="$str $i"
i=`expr $i + 1`
done
echo $str
until 命令或表达式
do
...
done
until与while功能相似,所不同的是只有当测试的命令或表达式的值
为假时,才执行循环体中的命令列表。若条件成立则退出循环。这一点
与while恰好相反。
break 和 continue
break n 跳出n层循环
contine n 转到最近n层循环语句的下一伦循环去
break和contine后面不加n,则和C语言里面的含义一样
shell 函数
function_name()
{
...命令列表
echo $1 $2 $3
return 123
}
function_name:你自定义的函数名,名字的取法与C语言类似
函数的调用
function_name arg1 arg2 arg3
在函数内部 arg1==>$1 arg2==>$2 arg3==>$3...
如何获取函数的返回值:通常有两种方式
1. ret=function_name arg1 arg2 arg3 //有些不支持
2. function_name arg1 arg2 arg3
ret=$?
注意:(1)函数的返回值的大小不超过一个字节
(2)SHELL没有变量作用域,如果出现重复变量名会认为是同一个。
eg:
get_sum()
{
return `expr $1 + $2`
}
read var1;read var2
get_sum $var1 $var2
echo $?