shell脚本中变量定义
shell语法中变量定义规则与C语言一致,只能使用数字,字母,下划线组成,并且不能以数字开头!
shell变量不需要声明数据类型,因为所有变量都是默认是字符串类型。
C语言: int a / char b /char * c
shell: a -> 默认是字符串类型
shell语法中为变量赋值时,等号的两边绝对不允许有空格!
C语言: int a = 100; / int a=100; -> 正确
shell: a = helloworld -> 错误
shell: a=helloworld -> 正确
shell语法对变量进行引用,需要在变量前面加$
C语言:
int a = 100;
printf("%d\n",a); -> C语言中不需要添加任何的符号,只需要直接写变量名即可。
shell:
a=helloworld
echo $a
shell语法变量种类
1)自定义变量 str=hello
2)系统环境变量 通过shell命令: "env"进行查看。
HOME=/home/myzr
PWD=/home/myzr
PATH=/usr/arm/arm-
HOME/PWD/PATH都是属于系统的环境变量名字
3)命令行变量 类似于C语言argc与argv
C语言: ./project aaa bbb
结果: argc=3
argv[0] = “./project”
argv[1] = “aaa”
argv[2] = “bbb”
shell: ./test.sh aaa bbb
$# ->命令行额外参数的个数:2 (不包括./test.sh在内)
$1 ->第1个额外传递的参数: aaa
$2 ->第2个额外传递的参数: bbb
$* ->代表所有的参数: aaa bbb
$? ->最后一条shell命令执行完的返回值 执行成功:0 执行失败:非0
练习1:写一个shell脚本,分别使用变量与命令行输入helloworld
#!/bin/bash
str=helloworld
echo $str
echo $#
echo $1
shell编程符号
- 双引号 作用:将某些东西变成一个值
1)字符串有空格情况
str=helloworld 正确
str=“helloworld” 正确
如果字符串中没有空格,则有没有双引号都可以!
str=hello world 不正确
str=“hello world” 正确
如果有空格,则必须要添加双引号才是一个整体!
2)在""中引用变量
str=hello
echo “$str world”
结果: hello world
3)在""中使用shell命令
date
Fri May 31 10:30:50 PDT 2019
echo "today is date" 结果: today is date
echo "today is $date" 结果: today is
echo "today is `date`" 结果: today is Fri May 31 10:36:09 PDT 2019
单引号 作用: 把单引号括住的内容看作是一个字符串
echo "today is `date`" 结果: today is Fri May 31 10:36:09 PDT 2019
echo 'today is `date`' 结果: today is `date`
反引号 作用:把双引号中的命令标识出来,把反引号的内容当做是一个shell命令。
字符串处理
- 计算字符串的字符个数
str=as[fjsdfoiweimvmawimismaffdasgeabre
echo “${#str}” -> #变量名:代表计算字符串的字符长度。
常用通配符:
- 代表任意长度的任意字符
? 代表一个长度的任意字符
[a-z] 代表一个长度的a-z之间的字符
[az] 代表一个长度,只能匹配a或者z的内容
[^az] 代表一个长度除了a或者z之外的字符,与[az]相反!
匹配原则:
#: 从左到右尽可能少地匹配字符
##:从左到右尽可能多地匹配字符
%: 从右到左尽可能少地匹配字符
%%:从右到左尽可能多地匹配字符
删除字符串左边的内容
str=hello123abc32world 从左边进可能多删除"xxxx32"
echo "${str##*32}" world ##*20 从字符串的左边开始拼了命去找*20这种东西。
echo "${str#*32}" abc20world #*20 从字符串中左边开始找这种*20的东西,只要找到一个,就行了。
echo "${str%20[az]*}" -> hello3
echo "${str%%20*}" -> hello3
测试语句
在C语言中判断值等于,不等于,大于,小于,判断文件是否存在,权限…
在linux中,使用test命令就可以进行测试。
NAME
test - check file types and compare values 检查文件的类型与比较值。
判断命令行参数是不是等于2个,如果不是两个就输出一个字符串"input arg error"报错!
测试语句写法一:
if test $# -ne 2
then
echo “input arg error”
fi
测试语句写法二:
if [ $# -ne 2 ]
then
echo “input arg error”
fi
分支控制语句
C语言分支: if-else switch
C语言循环: for while do-while
shell分支: if-else case
shell循环: for while until
if-else分支
框架:
if 判断条件1 使用测试语句
then 判断条件1正确,则执行xxxx
xxxx
elif 判断条件2
then 判断条件2正确,则执行yyyy
yyyy
else --> 如果全部条件都不满足,则执行zzzz,else之后是没有then。
zzzz
fi
判断命令行参数的值
个数>2 则输出 “hello”
个数=2 则输出 “world”
个数<2 则输出 “error”
#!/bin/bash
if [ $# -gt 2 ]
then
echo "hello"
elif [ $# -eq 2 ]
then
echo "world"
else
echo "error"
fi
结论:
1)每一个if语句都有fi作为结束标志。
2)if后面的判断条件必须为真(0)时 -> 因为shell命令执行成功返回0,then后面的语句才会被执行。
3)linux命令后面加不加;都行。 echo “hello” 等价于 echo “hello”;
4)else后面是注意then。
练习3:要求命令行传递一个文件名,先判断文件是否存在,如果存在并且有读的权限,则在终端上打印文件的内容。 &&
如果文件存在,但是没有读的权限,则添加修改文件的权限之后,再输入文件的内容。如果文件不存在,则输出"file not exist"
./p3.sh a.txt 如果参数不是1个,则程序直接退出。 -> 执行exit命令可以直接退出程序。
#!/bin/bash
if test $# -ne 1
then
echo "input argument error!"
exit
fi
if [ -r $1 ]
then
cat $1
elif [ -e $1 ]
then
chmod 777 $1
cat $1
else
echo "file not exist"
fi
C语言: 调用exit(0)直接程序
access() 判断文件权限以及文件是否存在 man 2 access
#include <unistd.h>
int access(const char *pathname, int mode);
pathname:需要判断的文件的路径
mode: F_OK -> 检测文件是否存在 access(“a.txt”,F_OK); -> 检测当前目录下的a.txt是否存在
R_OK -> 是否可读
W_OK -> 是否可写
X_OK -> 是否可执行
返回值:
可读/可写/可执行/存在 -> 0
不可读/不可写/不可执行/不存在 -> -1
system() 在C语言程序中调用一些shell命令 man 3 system
#include <stdlib.h>
int system(const char *command);
command: 需要执行的shell命令 --> system(“cat a.txt”);
返回值:
写入命令,正确执行 0
写入命令,错误执行 -1
写入命令为NULL 非0
sprintf() 拼接字符串
char *p = “a.txt”;
char buf[50];
bzero(buf,50);
sprintf(buf,“cat %s”,p); p->%s -> “a.txt”->%s -> “cat a.txt” -> buf
printf(“buf:%s\n”,buf); “cat a.txt”
system(buf);
结论:在C语言中调用shell命令,巧妙使用sprintf()与system()搭配。
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
int main(int argc,char *argv[]) // ./p3 a.txt
{
if(argc != 2)
{
printf("input argument error!\n");
exit(0);
}
char buf[100];
bzero(buf,100);
if( (access(argv[1],F_OK)==0) && (access(argv[1],R_OK)==0) )
{
sprintf(buf,"cat %s",argv[1]);
system(buf);
}
else if( access(argv[1],F_OK)==0 )
{
sprintf(buf,"chmod 777 %s",argv[1]);
system(buf);
bzero(buf,100);
sprintf(buf,"cat %s",argv[1]);
system(buf);
}
else{
printf("file not exist!\n");
}
return 0;
}
case语句
case语句与C语言中的switch语句非常相似,都是用于判断多种条件情况。
C语言switch语句
switch(变量) -> 整型,字符型,枚举类型
{
case xx: -> 如果变量等于xx,则执行xxx这个表达式。
xxx;
break;
case yy: -> 如果变量等于yy,则执行yyy这个表达式。
yyy;
break;
default: -> 变量都不等于上述的值,就执行zzz这个表达式
zzz;
break;
}
shell中case语句
case 变量 in
xx) xxx;; -> 如果变量等于xx,则执行xxx这个表达式。
yy) yyy;; -> 如果变量等于yy,则执行yyy这个表达式。
*) zzz;; -> 变量都不等于上述的值,就执行zzz这个表达式
esac
从键盘中获取值
C语言:
int a;
scanf("%d",&a);
shell: -> 使用read命令
read a
$ /mnt/hgfs/GZ1927/06 shell编程/code$ read a
helloworld 从键盘中输入
$ /mnt/hgfs/GZ1927/06 shell编程/code$ echo $a
helloworld
执行程序之后,从键盘中获取一个值,如果该值为1,则打印"one",如果该值为10,则打印"ten",如果都不是,则打印"error"。
#!/bin/bash
read a
case $a in
1) echo “one” ;;
10) echo “ten” ;;
*) echo “error”;;
esac
假设当前目录下有一个文件名字为a.txt,文件的内容为10(自己写进去),要求写一个脚本,判断文件的内容
内容为10,则打印"large"
内容为5,则打印"middle"
内容为1,则打印"small"
其他值,则打印"error"
要求使用命令行传递文件: ./test.sh a.txt
#!/bin/bash
if [ $# -ne 1 ]
then
echo "input arg error"
exit
fi
var="`cat $1`"
case $var in
10) echo "large";;
5) echo "middle";;
1) echo "small";;
*) echo "error";;
esac
for循环
把传递进来的命令行参数全部打印出来。 ./test.sh aaa bbb
#include <stdio.h>
int main(int argc,char *argv[]) // ./xxx aaa bbb
{
int i;
for(i=0;i<argc;i++)
{
printf(“argv[%d] = %s\n”,i,argv[i]);
}
return 0;
}
结果:
argv[0] = “./xxx”
argv[1] = “aaa”
argv[2] = “bbb”
$# 个数 2
$* -> 全部的参数 "aaa bbb"
for循环框架
for 变量 in 约束条件 例子: for s in
∗
−
>
s
依
次
赋
值
* -> s依次赋值
∗−>s依次赋值*的每一个值 1. s=aaa 2. s=bbb 3. 假
do -> 循环条件满足,则执行do的内容
xxxx
xxxx
done
#!/bin/bash
declare -i n=0 // i(integer)为整型
n=0 // n默认是字符串类型
for var in
∗
d
o
e
c
h
o
"
a
r
g
[
* do echo "arg[
∗doecho"arg[n]:
v
a
r
"
n
=
var" n=
var"n=n+1
done
执行./for.sh aaa bbb ccc ddd eee
arg[0]:aaa
arg[1]:bbb
arg[2]:ccc
arg[3]:ddd
arg[4]:eee
while循环
框架:
C语言while循环:
while(判断条件)
{ //循环体
xxxx; -> 循环内容
}
shell while循环
while 判断条件 -> 一般都是使用测试语句
do //循环体
xxxx; -> 循环内容
done
练习4: 使用while循环打印1~100值
#!/bin/bash
declare -i n=1
while [ $n -le 100 ]
do
echo $n
n=$n+1
done
while死循环
#!/bin/bash
declare -i n=1
while [ $n -eq 1 ]
do
n=1
done
until循环
while 当什么什么条件成立,就执行循环。
until 直到什么什么条件成立了,不执行循环了。
框架:
until 判断条件 -> 一般都是使用测试语句
do //循环体
xxxx; -> 循环内容
done
使用until循环打印1~100值
#!/bin/bash
declare -i n=1
until [ $n -gt 100 ]
do
echo
n
n
=
n n=
nn=n+1
done