加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

2019年7月23日星期二(shell编程)

发布时间:2020-12-16 01:55:38 所属栏目:安全 来源:网络整理
导读:一 . shell 编程的理解? 1. 什么是 shell 编程? shell编程通过 shell语法写出来的文件,这个文件叫 shell脚本。例如: Ubuntu中的 “~/.bashrc”、开发板中的 “/etc/profile”, shell编程有自身独特变量定义,循环结构,分支结构。 2. 怎么理解 shell ?

. 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 "hellon"?? -> 加了-e,就会解析n

hello

[email?protected]:/bin$ echo "hellon"

hellon

综上所述,helloworld脚本应该是:

shell脚本:

--------------------------------

#!/bin/bash

echo "helloworld"

--------------------------------

练习1:写一个脚本,要求输出以下的信息。

1. GZ1934<Tab键>guanguoyuan<Tab键>192.168.90.2

2. GZ1934

?? guanguoyuan

?? 192.168.90.2

?

#!/bin/bash

echo -e "GZ1934tguanguoyuant192.168.90.2"

echo -e "GZ1934nguanguoyuann192.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("%dn",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语言中argcargv

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通配符:? (通用的匹配符号)

*: 代表任意长度的任意字符。

?: 代表一个长度的任意字符。

[a-z]: 代表一个长度的a-z之间的字符

[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分支? -> 针对多种情况

1C语言中swtich语句框架

switch(变量)? -> 整型,字符型,枚举类型

{

?????? case xx:

????????????? xxxx;

????????????? break;

?????? case yy:

????????????? yyyy;

????????????? break;

?????? default:

????????????? zzzz;

????????????? break;

}

2shellcase分支框架

case 变量 in

?????? xx)?? xxxx;;

?????? yy)?? yyyy;;

?????? *)??? zzzz;;

esac

拓展:

C语言从键盘获取整型数据

int a;

scanf("%d",&a);

shell

read a?? -> 阻塞从键盘中获取一个值,存放在a变量中

[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

2shell中整型数据

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读