一. shell编程的理解?
1. 什么是shell编程?
shell编程通过shell语法写出来的文件,这个文件叫shell脚本。例如:Ubuntu中的“~/.bashrc”、开发板中的“/etc/profile”,shell编程有自身独特变量定义,循环结构,分支结构。
2. 怎么理解shell?
shell在英文中翻译为"贝壳",在贝壳的内部叫内核,在贝壳的外部叫用户,用户与内核之间进行交互必须通过shell来进行解析。
例子:
用户 shell 内核
输入ls -> ls就是shell命令,使用shell命令解析进行解析 -> 通知内核打印当前目录下所有文件。
3. 如何解析命令?是谁在解析命令?
1)解析命令必须有命令行,所以使用命令行之前必须打开一个linux终端,打开一个终端后,会自动运行一个bash进程。因为命令行"[email protected]:~$"就是bash进程打印出来的。
2)其实就是bash进程在解析命令,也就是说没有命令行,命令是无效。
4. linux终端、bash进程、shell命令是什么关系?
[email protected]:~$ ps -ef -> 查看当前系统中所有进程。
用户名 进程ID 父进程ID 进程的名字
gec 3950 1 0 18:26 ? 00:00:00 gnome-terminal -> linux终端
gec 3956 3950 0 18:26 pts/0 00:00:00 bash -> bash进程,是linux终端的子进程
gec 4024 3956 0 18:30 pts/0 00:00:00 ps -ef -> shell命令,是bash进程的子进程
二. shell编程
1. 什么是shell脚本?
其实就是使用shell语法组织出来的一个文件,将来运行这个文件,就会依次执行里面每一行的shell语法,这个文件叫称之为shell脚本。
2. C语言程序与shell编程区别?
C语言程序 shell脚本文件
==================================================================
语法: C语言 shell语法
是否需要编译: 需要编译器编译 不需要编译,但是必须有解析器
文件后缀: xxxx.c xxxx.sh
3. C语言程序与shell编程运行步骤对比:
C语言:
1. 创建文件 touch xxxx.c
2. 编辑程序 gedit xxxx.c
3. 编译程序 gcc xxxx.c -o xxxx
4. 执行程序 ./xxxx
shell:
1. 创建文件 touch xxxx.sh
2. 编辑脚本 gedit xxxx.sh
3. 修改脚本权限 chmod 777 xxxx.sh
4. 执行脚本 ./xxxx.sh
三. shell脚本helloworld程序。
C语言:
-----------------------------
#include <stdio.h>
int main()
{
printf("helloworld!\n");
return 0;
}
-----------------------------
shell脚本:
没有main函数,由于shell中不能调用函数,所以也不需要包含头文件,但是必须要指明一个东西,那么就是/bin/bash。
1. 怎么指明?
shell脚本中第1行必须是: #!/bin/bash -> 作用: 指明解析器的路径
2. shell中如何输出字符串到终端上?
[email protected]:/bin$ man 1 echo
NAME -> 对功能进行简单概括
echo - display a line of text -> 显示文本
DESCRIPTION
Echo the STRING(s) to standard output. -> 将字符串输出到标准输出上。
-e enable interpretation of backslash escapes -> 解析字符串上的转义符号 \
例子:
[email protected]:/bin$ echo -e "hello\n" -> 加了-e,就会解析\n
hello
[email protected]:/bin$ echo "hello\n"
hello\n
综上所述,helloworld脚本应该是:
shell脚本:
--------------------------------
#!/bin/bash
echo "helloworld"
--------------------------------
1. GZ1934<Tab键>guanguoyuan<Tab键>192.168.90.2
2. GZ1934
guanguoyuan
192.168.90.2
#!/bin/bash
echo -e "GZ1934\tguanguoyuan\t192.168.90.2"
echo -e "GZ1934\nguanguoyuan\n192.168.90.2"
四. shell脚本的变量定义。
1. shell语法变量定义规则与C语言一致,只能使用下划线,数字,字母组成,并不能以数字开头。
2. shell变量不需要声明数据类型,所有变量默认都是字符串类型
C语言: int a / char b
shell: a -> 默认就是字符串
3. shell语法中给变量赋值时,等号的两边不允许有空格
C语言: int a = 100; / int a=100; --> OK
Makefile: CC = gcc / CC=gcc --> OK
shell: a=helloworld -> OK a = helloworld -> Error
4. shell语法对变量的引用,需要在变量前面添加$
C语言:
int a = 100;
printf("%d\n",a); -> 在C语言中引用变量不需要添加任何符号。
shell:
a=helloworld
echo $a
例子:
#!/bin/bash
str = hello -> 由于有空格,语法有误。但是不导致程序停止运行。
echo $str world
5. 变量种类。
1)自定义变量 str=helloworld
2)系统环境变量 -> 通过shell命令"env"来查看。
PWD=/mnt/hgfs/GZ1934/05 shell编程/01/code
PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/arm/bin:/home/gec/project:/usr/arm/arm-2009q3/bin
SHELL=/bin/bash
其中: PWD、PATH、SHELL就是系统的环境变量名字,自定义变量的名字不能与系统环境变量同名。
3)命令行变量 -> 类似于C语言中argc与argv
C语言: ./hello aaa bbb
argc = 3
argv[0] = "./hello"
argv[1] = "aaa"
argv[2] = "bbb"
shell中也是可以传递参数: ./hello.sh aaa bbb
$#: 命令行额外(不算"./hello.sh"在内)的参数个数: $#=2
$1: 第一个额外的参数: $1=aaa
$2: 第二个额外的参数: $2=bbb
$*: 代表所有的参数 $*=aaa bbb
$?: 最后一条shell命令执行完的返回值 shell命令执行成功:0 执行失败:非0
练习2:写出命令行版helloworld脚本。
#!/bin/bash
echo $1
结果:
./p2.sh helloworld
五. shell编程符号。
1. 双引号 -> 作用:将某些东西变成一个"值"
1)字符串内部有空格时
str=helloworld -> 正确
str="helloworld" -> 正确
当双引号中字符串中没有空格时,加不加双引号。
str="hello world" -> 正确
str=hello world -> 错误 -> 如果有空格,必须添加双引号。
2)在""中能不能双引号变量?
可以使用。
3)在""能不能用linux命令?
可以使用,但是命令需要使用反引号(`)标识出来。
#!/bin/bash
echo "today is date" -> 结果: today is date
echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019
2. 单引号 -> 作用:把单引号括起来的内容看作是一个字符串。
echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019
echo ‘today is `date`‘ -> 结果: today is `date`
3. 反引号 -> 作用:把双引号中的命令标识出来。
echo "today is `date`" -> 结果: today is Mon Jul 22 19:58:15 PDT 2019
4. 重定位符号 > <
六. 字符串处理
1. 计算字符串的字符个数
str=helloworld20helloworld30ashfadsghdcfytzvxcsdhfvtyasdvausd
echo "${#str}"
2. 删除字符串左边/右边内容。
常见shell通配符: (通用的匹配符号)
*: 代表任意长度的任意字符。
?: 代表一个长度的任意字符。
[az]: 代表一个长度,只能匹配a/z字符
[^az]: 代表一个长度,只能匹配除了a或者z之外的字符,与[az]
#: 从左到右尽可能匹配少的字符
##: 从左到右尽可能匹配多的字符
%: 从右到左尽可能匹配少的字符
%%: 从右到左尽可能匹配多的字符
删除字符串左边一些字符,例子:
str=hello320abc20world
echo "${str##*20}" -> 从左到右尽可能多地删除这种"*20"的东西 -> 结果:world
echo "${str##*[^ac]20}" -> 从左到右尽可能多地删除 除了*a20/*c20 -> 结果:abc20world
echo "${str##*[ac]20}" -> 从左到右尽可能多地删除 *a20/*c20 结果:world
删除字符串右边一些字符,例子:
echo "${str%%20*}" -> 结果: hello3
echo "${str%20*}" -> 结果: hello320abc
练习3:
str=hello345abcsd3ffworldf45hello123world45hello
1. 计算字符个数
2. echo "${str##*3[a-z]}" orld45hello
3. echo "${str%3[a-z]*}" hello345abcsd3ffworldf45hello12
七.测试语句?
1. 什么是测试语句?
其实测试就是比较两个值的大小。类似C语言中"=="、"!="、strcmp()
2. 测试语句需要使用到test命令。 -> man 1 test
NAME
test - check file types and compare values -> 测试文件类型以及比较值。
SYnopSIS -> 使用格式
test EXPRESSION 等价于 [ EXPRESSION ]
DESCRIPTION -> 详细参数描述。
INTEGER1 -eq INTEGER2
INTEGER1 is equal to INTEGER2
INTEGER1 -ne INTEGER2
INTEGER1 is not equal to INTEGER2
例子: 测试3是不是等于2
test 3 -eq 2 等价于 [ 3 -eq 2 ]
八. 分支结构语句
C语言分支:if-else switch
C语言循环:for while do-while
shell分支:if-else case
shell循环:for while until
1. if-else分支
框架:
if 判定条件(测试语句)
then
xxxx
elif 判定条件(测试语句)
then
yyyy
else
zzzz
fi
2. 注意事项:
1)测试语句的[]的两边不允许有空格。
2)每一个if语句都会fi作为结束标志。
3)if后面的判定条件为真(0)时,then后面的语句才会被执行。
4)else后面是没有then的。
例题:判断命令行参数是不是为2个,如果不是2个就输出一个字符串报错。
#!/bin/bash
if [ $# -ne 2 ]
then
echo "input arg error"
fi
-----------------------
#!/bin/bash
if test $# -ne 2
then
echo "input arg error"
fi
练习4: 使用命令行传递文件名参数,例如: ./xxx.sh 1.txt,如果参数不等于1个,则输出字符串报错。判断该文件是否存在,如果存在,则在终端输出文件的内容,如果文件存在,但是没有读的权限,那么就添加读权限之后,再输出文件的内容,如果文件不存在,则输出字符串"file not exist"这个字符串来报错!
#!/bin/bash
if test $# -ne 1
then
echo "input arg 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语言中完成这道题。
1. 在程序中如何直接退出程序? -> exit() -> man 3 exit
#include <stdlib.h>
void exit(int status);
status: 退出时状态
一般正常为0,异常为非0
返回值:无
例子: exit(0) -> 直接正常退出程序
exit(-1) -> 直接异常退出程序
2. 判断文件权限以及文件是否存在 -> access() -> man 2 access
NAME
access - check real user‘s permissions for a file -> 判断文件权限,以及文件是否存在。
#include <unistd.h>
int access(const char *pathname,int mode);
pathname:需要判断的文件的路径
mode: F_OK -> 判断文件是否存在
R_OK -> 判断文件是否存在并可读
W_OK -> 判断文件是否存在并可写
X_OK -> 判断文件是否存在并可执行
返回值:
成功:存在,存在可读,存在可写,存在可执行 -> 0
失败:-1
3. 在C语言中如何执行linux命令? -> system() -> man 3 system
NAME
system - execute a shell command -> 执行shell命令
#include <stdlib.h>
int system(const char *command);
command: 需要执行的linux命令
返回值:
成功:0
失败:-1
4. 拼接字符串 -> sprintf() -> man 3 sprintf
#include <stdio.h>
int sprintf(char *str,const char *format,...);
str: 缓冲区地址
format: 格式
...: 额外的参数
argv[1] = "1.txt"
char buf[50] = {0};
printf("cat %s",argv[1]); //将cat 1.txt打印在屏幕上
sprintf(buf,"cat %s",argv[1]); //将"cat 1.txt"保存到buf数组中
参考:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
int main(int argc,char *argv[]) //./p4 xxx
{
if(argc != 2)
{
printf("input arg error!\n");
exit(-1);
}
char buf[50];
bzero(buf,50);
if(access(argv[1],R_OK) == 0) //存在并可读
{
sprintf(buf,argv[1]);
system(buf);
}
else if(access(argv[1],F_OK) == 0) //存在
{
sprintf(buf,"chmod 777 %s",argv[1]);
system(buf);
bzero(buf,50);
sprintf(buf,argv[1]);
system(buf);
}
else //不存在
{
printf("file not exist!\n");
}
return 0;
}
2. case分支 -> 针对多种情况
1)C语言中swtich语句框架
switch(变量) -> 整型,字符型,枚举类型
{
case xx:
xxxx;
break;
case yy:
yyyy;
break;
default:
zzzz;
break;
}
2)shell中case分支框架
case 变量 in
xx) xxxx;;
yy) yyyy;;
*) zzzz;;
esac
拓展:
int a;
scanf("%d",&a);
shell
[email protected]:/mnt/hgfs/GZ1934/05 shell编程/01/code$ read a
hello
[email protected]:/mnt/hgfs/GZ1934/05 shell编程/01/code$ echo $a
hello
练习5:执行程序后,从键盘中获取一个值,如果该值为1,则打印one,如果为10,就打印ten,如果都不是,则打印error
#!/bin/bash
read a
case $a in
1) echo "one";;
10) echo "ten";;
*) echo "error";;
esac
练习6:假设有一个文件名字叫test.txt,内容为10,要求写一个脚本,判断文件的内容
内容为10,则打印large
内容为5,则打印middle
内容为1,则打印small
其他值,则打印error
./test.sh test.txt --> 要求判断传参问题。
#!/bin/bash
if [ $# -ne 1 ]
then
echo "input arg error"
exit
fi
val="`cat $1`"
case $val in
10) echo "large";;
5) echo "middle";;
1) echo "small";;
*) echo "error";;
esac
3. while循环
1)框架:
C语言:
while(判定条件)
{ //循环体
.... -> 循环内容
}
shell:
while 判定条件(测试语句)
do //循环体
.... -> 循环内容
done
2)shell中整型数据
str -> 默认是字符串类型
declare -i str -> str就是整型数据
----------------------------------------
#!/bin/bash
str=100
str=$str+1
echo $str -> 结果: 100+1
---------------------------------------
#!/bin/bash
declare -i str=100
str=$str+1
echo $str ->结果: 101
-----------------------------------------
练习7: 使用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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。