1.shell脚本
shell是一个命令解析器
我们可以把很多需要用到命令,以某种语言或者某种方式组织起来
交给shell去执行,这种命令的组织方式,称之为shell脚本语言。
xxx.sh是包含多个命令的shell脚本文件
shell脚本文件也是一个普通文本文件,是以shell脚本语言的方式
把多个命令组织起来的普通文件。
./xxx.sh 把这些脚本语言可执行文件交给shell命令解析器去执行。
shell脚本 也是一个文本文件
按照shell脚本语言写的文件
最终也要通过shell命令解析器去执行
1.shell脚本文件
第一shell文件
vim 2.sh//创建一个.sh文件
#!/bin/bash shell指定的命令解析器
echo "hello world"//输出,类似于printf
改变脚本文件的权限
chmod +x 2.sh//为所有(当前用户,组用户,其他用户)增加可执行权限
运行脚本文件
./2.sh
2.shell变量
在shell脚本中,我们可以定义变量
shell脚本没有类型的概念,全部都是字符串
shell变量也不用定义,直接赋值就可以了
语法:
变量名=变量的值
注意:
=左右两边不能有空格!!!!!!!!!!
引用一个变量;
$变量名
${变量名}
如:
val="1234567"
echo $val
当变量内容如果存在空格(空字符),需要用''引起来
变量的内容可以累加到另外一个变量,需要用""引起来!!!
shell脚本的变量有四种
(1)自定义的变量
如:
val=250
$val
DATE=`date`
``:引用那个命令或者程序或者脚本文件的输出结果
`date`
(2)位置变量
指的是传递给脚本文件或函数的参数
如:
./1.sh 123 456 789
在shell脚本中或shell函数中
$0 第一个参数 命令行程序文件
$1 第二个参数 123
$2 第三个参数 456
...
$# 表示命令行参数(不包含脚本名)的个数
$@ 表示所有行命令参数(不包含脚本名)
$@<==>$1 $2 $3 ...
$* 包含所有行命令参数
$*<==>$1 $2 $3...
$? 表示前一个命令的退出码(返回值 进程退出值)
用来检测上一次命令执行是否正确
在linux里面 正常的退出值为0,其他非零表示出错
(3)环境变量
环境变量:在同一个终端下所有的进程都可以共享的变量
HOME:用户主目录的路径
如:
echo $HOME // /home/china
PATH:命令或者可执行程序的搜索路径
export:查看shell的环境变量
如果你想你得命令或者可执行程序,在运行的时候不需要指定路径
你的程序就必须放在环境变量的路径里面
(1) cp 2.sh /usr/bin
(2)改变环境变量的值
export PATH=$PATH:/home/china
3.shell数组
数组名[下标]=val 下标0,1,2,3...
引用一个数组:
引用整个数组(引用数组中所有元素)
${数组名[*]}
${数组名[@]}
引用单个元素
${数组名[下标]}
如果单独出现数组名,引用数组中第一个元素
数组名=(A B C D)
如:
data=(1 2 3 4 5)
echo {data[*]}
4.shell脚本的语句
说明性语句(注释)
以#开头的语句 注释行
功能性语句
任意的操作系统的系统命令(如 ls cd date echo)
shell内部的命令,自编程序,某些功能的语句
如:
cd /home/china
./a.out
read 在shell中表示从终端上获取输入
如:
read a b
从键盘获取两个字符串,第一字符串保存在变量a
第二字符串保存在变量b,两个字符串输入的时候需要用空格
隔开
例子:
read val1 val2
echo $val1
echo $val2
如果只是输入一个参数,那么就给val1赋值 val2就是一个空串
如果输入的参数超过两个的话,第一个参数赋值给val1,后面剩余所有的参数
都会赋值给val2,且也会保留中间的空格
expr 算数运算符命令
expr主要进行简单的整数运算,包括:
+ - / \* %
如:
expr 5 + 3 (操作数和运算符之间,前后必须加一个空格)
ret=`expr 5 + 3`
echo $ret
i=6
a=`expr $i + 4 \* 2`
echo $a
练习:
写一个shell脚本,计算两个整数之和
这两个整数需要作为参数输入
./1.sh 123 456
$1-->123
$2-->456
test 测试语句
test可以测试三种对象:字符串 整数 文件
(1)字符串
= 测试两个字符串是否完全一致
test "abc" = "abc" //如果相等返回0 不相等返回1
echo $?
!= 测试两个字符串是否不一致
test "abc" != "ac"
echo $? //如果不一致打印0 一致打印1
-z zero测试字符串是否为空
test -z ""
echo $? //为空打印0
-n not null测试字符串是否不为空
test -n "abd"
echo $? //不为空打印0
例子:
str=""
test -z $str
echo $?
例子:
判断变量a和变量b是否相等,a和b都是从参数输入
test $1 = $2
echo $?
从键盘输入一个字符串,测试它是否等于"good"
read s
test $s = "good"
echo $?
这时如果输入为空,等号左边少了一个操作数
会有语法错误
改成:
test "$s" = "good"
(2)整数测试
a -eq b equal测试两个整数是否相等
如:
test 4 -eq 3
echo $? #1
test 3 -eq 3
echo $? #0
a -ne b not equal测试两个整数是否不相等
如;
test 4 -ne 3
echo $? #0
a -gt b greater than 测试a>b 如果a大于b返回0
如:
test 4 -gt 3
echo $?
a -lt b little than 测试a
如:
test 3 -lt 4
echo $?
a -ge b greater and equal测试a>=b 如果a大于等于b返回0
如:
test 4 -ge 3
echo $?
a -le b little and equal 测试a<=b 如果a小于等于b返回0
如:
test 3 -le 4
echo $?
(3)文件测试
-d filename 测试filename是否是一个目录(directory)
test -d 1.txt
echo $? #1
-f filename 测试filename是否是一个普通文件(file)
test -f 1.c
echo $? #0
-L filename 测试filename是否是一个链接文件(Link)
test -L 8.c
echo $? #0
-r filename 测试filename是否可读(read)
-w filename 测试filename是否可写(write)
-x filename 测试filename是否可执行(excute)
-s filename 测试filename是否存在且长度不为0(size)
file1 -nt file2 测试file1是否比file2更新(newer than)
file1 -ot file2 测试file1是否比file2更旧(older than)
test命令也可以用[]来替代
test 表达式(expression) 《==》 [ 表达式 ]([]两边必须要有空格)
如:
test 2 -eq 3 <==> [ 2 -eq 3 ]
test的复合表达式
组合两个或者两个以上的表达式成为复合表达式
使用复合表达式,用test的内置的操作符,也可以用条件操作符
(1)使用test内置操作符来创建一个复合表达式
test exper1 "选项" exper2
选项;
-a and
-o or
例子:
test -f $1 -a -nt $2
测试$1这个文件是不是一个普通文件,并且这个文件是不是比$2文件要新
(2)使用条件运算符(&& ||)来创建一个复合表达式
test exper1 "op" exper2
例子:
test -f $1 && -nt $2
测试$1这个文件是不是一个普通文件,并且这个文件是不是比$2文件要新
结构性语句(分支语句 循环语句)
(1) c语言中条件语句
if()
{
}
else
{
}
shell脚本中
if command ; then
语句列表1
语句列表2
else #如果没有else可以不写
语句列表1
语句列表2
fi
例子:
if [ -f $1 ];then
echo "regular file"
else
echo "not regular file"
fi
例子:从键盘获取一个整数,判断这个数是否是奇数
read a
i=`expr $a % 2`
if [ $i -eq 1 ];then
echo "odd number"
else
echo "not odd number"
fi
(2)多路分支语句
c语言:
switch(表达式)
{
case 常量表达式1:
语句1;
break;
case 常量表达式2:
语句2;
break;
...
default:
语句;
break;
}
shell脚本:
case 字符串变量 in
模式1)
....
;;
模式2)
....
;;
模式3)
....
;;
esac
case语句非常强大他可以使用模式
而不是使用固定的字符串
一个模式是由一串正规的字符或特殊的通配符组成的字符串
该模式可以用正则表达式
例子:
filename=$1
case $filename in
*.c)
echo "C source file"
;;
*.h)
echo "h file"
;;
*.cpp)
echo "C++ source file"
;;
esac
";;": 作用类似于C语言中的break但是shell脚本中 ;; 不可以省略的
(3)循环语句
语法:
for 变量名 in 单词表
do
循环体语句
done
“单词表”;以空白字符分隔开的字符串列表
如: a ab abc erer 123
for 循环的次数就是单词表中单词的个数
每次循环,变量的值就是单词表中的值
例子:
for val in a b c 123 xyz
do
echo $val
done
练习:
使用for循环实现1-5之和
sum=0
for i in 1 2 3 4 5
do
sum=`expr $sum + $i`
done
echo $sum
for语句也可以写成C语言的风格相同类型:
(())来替代
例子;
求100以内的所有整数和
sum=0
for((i=0;i<100;i++))
do
sum=`expr $sum + $i`
done
echo $sum
练习:
写一个shell脚本,计算1000以内3的倍数的数字之和
sum=0
for((i=0;i<1000;i=i+3))
do
sum=`expr $sum + $i`
done
echo $sum
语法;
while 命令或表达式
do
循环体语句
done
sum=
i=0
while [ $i -le 5 ]
do
sum=`expr $sum + $i`
i=`expr $i + 1`
done
练习:
写一个shell脚本,计算一个1.txt文件中有多少行数据
read 输入重定向
line=0
while read val
do
line=`expr $line + 1`
read < $1
done < $1
echo $line
语法:
until 命令或者表达式
do
循环体语句
done
until功能跟while是相似的
不同的是until只有当命令或者表达式的值为假
才会执行循环体语句
当条件成立,则退出循环 这个点跟while刚好相反
例子
i=0
until [ $i -gt 100]
do
echo $i
done
==>
i=0
while [ $i -gt 100 ]
do
echo $i
done
break 和 continue用法和C语言用法是一样的
练习:
写一个shell脚本,从键盘输入一个数,判断这个数是否是质数。
n=$1
flag=1
i=2
while [ $i -lt $n ]
do
ret=`expr $n % $i`
if [ $ret -eq 0 ];then
flag=0
break
fi
i=`expr $i + 1`
done
if [ $flag -eq 1 ];then
echo $n
fi
写一个shell脚本,打印2-1000以内所有的质数
n=2
while [ $n -le 1000 ]
do
./111.sh $n #nb(这里理解为这句话nb就可以了)
n=`expr $n + 1`
done
(4)shell函数
语法:
function_name()
{
函数体
}
shell中函数是没有返回值类型,也没类型
function_name取名规则 跟c语言一模一样
调用:
function_name arg1 arg2
在函数的内部使用arg1 arg2
$1 ==> arg1
$2 ==> arg2
...
获取函数的返回值
(1) ret=`function_name arg1 arg2`
例子;
sum()
{
a=$1
b=$2
s=`expr $1 + $2`
return $s
}
sum 3 4
echo $? #7