SHELL编程(一)概念 基本语法

一、概念

不同架构CPU所使用的指令集不同,编译器也不同。

(一)编译型语言和解释型语言

1. 编译型语言

在运行前需要专门有一个编译的过程,将方便人类识别的高级语言翻译成计算机识别的机器指令。

优点:执行前已经翻译过了,执行过程中无需重新翻译,所以执行效率相对较高
缺点:可移植性(跨平台)相对较差。
例:C语言、C++

2. 解释型语言(脚本语言)

运行前无需单独翻译,而是在运行过程由解释器逐行翻译给计算机。

优点:可移植性(跨平台性)相对较好,不依赖于编译器
缺点:每次执行都需要逐行重新翻译,执行效率相对较低
例:shell、python

(二)SHELL

1. shell

shell是命令行解释器。
/bin/bash
/bin/dash

  • 注:dash 是 bash 的轻量级

2. shell脚本

以’.sh’结尾的文件(方便人识别出这是shell脚本文件,对计算机并不是硬性要求),里面是命令的集合以及一些复杂的逻辑。

目的:批量的执行命令

(1)执行

shell是解释型语言,无需编译,直接运行即可
方式1:./脚本名
在这里插入图片描述

方式2:bash 脚本名
在这里插入图片描述

方式3:source 脚本名
在这里插入图片描述

  1. ./执行需要加执行权限,而bashsource不需要执行权限
  2. ./方式 和 bash方式是在后台新开了一个终端执行脚本,并把执行的结果返回当前终端;而source就是直接在当前终端执行,如果脚本中更改了文件目录,使用source运行该脚本也会更改路径

二、shell语法

(一) shell变量

1. 变量

在shell中使用变量时无需提前定义,直接使用即可
shell每条指令结束无需加分号,多条指令放在一行可以用分号分隔
shell中的变量默认都是字符串,没有整型、浮点数之分

shell变量使用也要符合变量的命名规范:
(1)数字字母下划线
(2)不能数字开头
(3)不能和shell的关键字冲突(如cd、ls)
(4)最好能望文知意
(5)变量名习惯上大写

(1)shell中的变量默认都是字符串
A1=100+200
A2=hello
echo $A1
echo $S1

输出结果:
在这里插入图片描述

(2) 赋值运算符两侧不能有空格

等号右侧如果有空格,会将空格赋值给变量,然后将空格后面的值当作命令执行,然后报错

A1= hello #hello前有空格
echo $A1

在这里插入图片描述
等号左侧如果有空格,会将变量名当作命令执行,然后报错

A1 =hello #A1后有空格
echo $A1

在这里插入图片描述

2. 引用变量

$<变量名>${<变量名>}

例:$a${a}
不要使用 $(变量名),这是命令置换符

  • 注:shell注释使用’#’
#!/bin/bash 

V1=hello

V2=1:${V1}world  
echo $V2   #1:helloworld

V3="hello world"  #如果字符串不加引号,遇到空格就会停止,然后将空格后的world当作命令执行
echo 2:$V3   #2:hello world

echo "3:双引号可以引用变量:$V1 world" #hello world

echo '4:单引号不能引用变量:$V1 world' #$V1 world

echo "5:花括号使用:${V1}world"  #helloworld

echo "6:不使用花括号会识别成为新变量,为空值:$V1world"   

输出结果:

在这里插入图片描述

3.清空变量的值

unset <变量名>

用于清空本地环境变量
在这里插入图片描述

  • 注意,后接变量名,不要加’$’
  • 在shell中既可以使用自定义变量,也可以使用环境变量

4.位置变量

类似于C语言中main函数的参数

  1. \$0 三种不同的执行方式值不同

./脚本名 $0就是 ./脚本名
bash $0就是脚本名
source $0就是bash

$1~9 命令行传递第一个到第九个
${10}超过九个参数时使用花括号,使其成为一个整体
$@ 执行脚本时命令行传的所有参数(不包括脚本名)
$* 执行脚本时命令行传的所有参数(不包括脚本名)
$# 执行脚本时命令行传的所有参数的个数(不包括脚本名)
$? 用来表示上一条命令是否执行成功 0成功;1没成功
$$ 执行脚本的进程号

echo '$0='$0
echo '$2='$2

在这里插入图片描述

5. 作用域

shell如果不加任何修饰,作用域默认是全局

如果想定义局部变量,加关键字"local"

6. shell的只读变量

关键字"readonly"

对只读变量修改会报错
需要初始化,因为后面不支持再修改

readonly V1=hello
echo '$V1='$V1
V1=world
echo '$V1='$V1

输出结果:
在这里插入图片描述

7. 命令置换符

将命令执行的结果赋值给变量

$() 或两个反引号 ` `

LIST=$(ls)
echo LIST=$LIST

LIST2=`ls`
echo LIST2=$LIST2

输出结果:
在这里插入图片描述

(二) 注释

1. 单行注释

#使用’#'单行注释

2. 多行注释

shell中并未真正定义多行注释语法,下面的用法利用了输入重定向,所以如果注释的内容有 读取终端输入的指令 可能就会有问题

:<<EOF

多行注释

EOF

或者

:<<!

多行注释

!

(三) 字符串相关操作

1. 计算字符串长度

${#<变量名>}

readonly V1=hello
echo ${#V1}

不会将’\0’计算进去
输出结果:
在这里插入图片描述

2. 字符串拷贝

shell中变量本身就是字符串,所以字符串拷贝本身就是变量的赋值

V1=helloworld
V2=$V1
echo '$V2='$V2

输出结果:
在这里插入图片描述

3. 字符串拼接

STRING1= ${STRING2}hello

V1=hello
V2=${V1}world
echo '$V2='$V2

输出结果:
在这里插入图片描述

4. 字符串截取

(1)${STRING:<num>}

从左往右下标为0开始数,第num个字符开始,一直到结尾

S1=aabbccddeeffgghh
echo ${S1:4}  #ddeeffgghh

输出结果:
在这里插入图片描述

(2)${STRING:<num1>:<num2>}

下标从0开始数,第num1个字符开始,截取num2个字符

S1=aabbccddeeffgghh
echo ${S1:4}  #ddeeffgghh

输出结果:
在这里插入图片描述

(3)${STRING:0-<num>}

倒数下标从1开始数,从倒数第num个开始截取,一直到结尾

S1=aabbccddeeffgghh
echo ${S1:0-4}  #gghh

输出结果:
在这里插入图片描述

(4)${STRING:0-<num1>:<num2>}

从倒数第num1个开始截取,截取num2个字符

S1=aabbccddeeffgghh
echo ${S1:0-4:2}  #gg

输出结果:
在这里插入图片描述

(5)其他截取字符串的方法

从左向右 截取第一次出现 rr 后面的内容

STRING="qqwweerrttqqwweerrttqqww"
echo ${STRING#*rr}

在这里插入图片描述

从左向右 截取最后一次出现 rr 后面的内容;

STRING2=${STRING##*rr}
echo $STRING2

在这里插入图片描述
从右向左 截取第一次出现 rr 前面的内容

STRING3=${STRING%rr*}
echo $STRING3  

在这里插入图片描述

从右向左 截取最后一次出现 rr 前面的内容

STRING4=${STRING%%rr*}
echo $STRING4 

在这里插入图片描述

(四) shell中的数组

1. 数组

ARR=(1 2 3 4 5)
echo ${ARR[1]} 

*注:

  1. shell只有一维数组,shell中的数组用()来表示
  2. shell的数组没有类型,默认都是字符串
  3. shell中的数组也无需提前定义
  4. 成员之间用空格分隔
  5. 下标也是从0开始

2. 赋值

数组名[下标]=新的值

ARR=(aa bb cc dd)
ARR[1]=ee
echo ${ARR[1]}

输出:
在这里插入图片描述

3. 引用

${ARR[1]}

4. 引用数组中所有的成员

${ARR[@]}
${ARR[*]}

赋值:

RET=${ARR[@]} #变量
RET=(${ARR[@]}) #数组

ARR=(aa bb cc dd)
RET=${ARR[@]}
RET2=(${ARR[*]})
echo RET #RET是一个字符串
echo RET2 #RET2是一个数组

在这里插入图片描述

5. 成员个数

${#ARR[@]}
${#ARR[*]}

ARR=(aa bb cc dd)
RET=${ARR[@]}
RET2=(${ARR[*]})
echo ${#RET} #RET是一个字符串
echo ${#RET2[@]} #RET2是一个数组

在这里插入图片描述

6. 追加成员

ARR=(11 22 ${ARR[@]} xx yy)

ARR=(aa bb cc dd)
ARR=(11 22 ${ARR[*]} 33 44)
RET=${ARR[@]}
echo $RET

在这里插入图片描述

(五)shell中的输入输出

1. 输出 echo

(1)echo自带换行符
A=hello
B=world
echo $A 
echo $B

在这里插入图片描述

(2)-n 取消换行符
A=hello
B=world
echo -n $A
echo $B

在这里插入图片描述

(3)-e 识别字符串中的换行符
S=hello\nworld
echo "0:hello\nworld"
#只能识别字符串中的换行符
echo -e "1:hello\nworld"
echo -e '2:hello\nworld'
#下面两种方式不能成功使用
echo -e 3:hello\nworld
echo -e 4:$S

输出:
在这里插入图片描述

2. 输入 read

(1)允许一次输入多个变量的值,以空格分隔
read A

read B C
#允许一次输入多个变量的值,以空格分隔,但是这种写法,一旦字符串中有空格,就无法识别了,所以不建议使用
(2)添加提示信息 -p
read -p "提示信息>>" A

在这里插入图片描述

(3)等待输入时间 -t(秒为单位)
read -t 5 #表示等待用户输入,最多等五秒,五秒后会继续向下执行,不敲回车无法读取
(4)最多获取字符 -n
read -n 5 #表示最多获取5个字符,只要输入够五个,不敲回车也读取
(5)获取数组 -a
read -a A#表示输入的是一个数组
read -p"这是一个数组>>" -a A
echo 数组大小为:${#A[@]}

在这里插入图片描述

(6)取消回显 -s
read -s #取消输入的回显

选项可以一次使用多个,搭配使用,但是选项和参数成对使用

eg :终端读取用户输入的软件名,输入后下载该软件,并执行该软件
要求有提示信息,最多20字符,最多等待10秒

#!/bin/bash
#输入
read -p "请输入要下载的软件名称>>" -n 20 -t 10  NAME
#下载
sudo apt-get install $NAME
#执行
$NAME

(六)shell中的运算符

shell用来批量执行命令,并不是专门用来做复杂的算术运算的。
如果需要处理复杂的算术运算,可以在shell中调用C程序

shell一般用于处理一些简单的运算,如计数变量的自增
shell如果不使用运算符直接运算,所有变量都会当作字符处理

shell不支持浮点运算

第一种:(())
第二种:$[]
第三种:let
第四种:expr

以上四种运算方式 效率是递减的,expr可以做字符串处理

1. ((表达式1,表达式2,…,表达式n))

多个表达式之间用逗号分隔
当有多个表达式时,每个表达式都会参与运算,最后一个表达式的结果是整个表达式的结果

  • 注:
  • 1. (())内部引用变量值$可加可不加
  • 2. 内部运算符前后的空格可加可不加
  • 3. 如果想使用结果需要加$ 例:‘$(())’
  • 4. 可以做复杂的算术运算,如变量自增自减以及for循环
  • 5.如果做自增自减运算,变量前就不能加$
    示例:((V1++))
read -p "please input V1: " V1                                                             
read -p "please input V2: " V2

echo "$V1 * $V2 = $((V1*V2))"
echo "++V1 = $((++V1))"

2. $[表达式1,表达式2,…,表达式n]

当有多个表达式时,每个表达式都会参与运算,最后一个表达式的结果是整个表达式的结果

V1=10;V2=20;V3=30;
V=$[++V1,++V2,++V3]
echo V=$V
echo V1=$V1" "V2=$V2

输出结果:
在这里插入图片描述

  • 注:
  • 1. 内部引用变量值$可加可不加
  • 2. 内部运算符前后的空格可加可不加
  • 3. 结果必须有变量来接或者echo到终端,否则报错
  • 4. 不能做复杂的运算,可以执行自加自减操作,不能执行for运算

3. expr

V2=20;V3=30;
expr $V2+$V3
expr $V2 + $V3

在这里插入图片描述

  • 注:
  • 1. expr内部引用变量值时$必须加,不加报错
  • 2. 内部运算符前后的空格必须加 ,不加空格当字符串处理
  • 3. 自动将结果打印到终端
  • 4. 如果想引用结果,需要命令置换符
  • 5. 不能做自加和自减
  • 6. expr计算乘法时需要使用转义字符

以下是错误的使用方法:

 expr V1++
 expr 2*3 #运算符两侧要有空格,否则当做字符串
 expr 2 * 3 #乘法不使用转义字符,会报错
 expr 2 \* 3 #正确的乘法  

在这里插入图片描述

(4)expr的其他用法

expr match 源字符串 子字符串

在源字符串中查找子字符串
如果源字符串中的,第一个字符和子字符串不相等结果为0
如果子字符串,有字符和源字符串中的字符不相等,返回的也是0.
否则返回的就是子字符串的长度。

#必须是从起点开始匹配 成功才返回长度
string=“www.hqyj.com.hqyj.com.qwer”
string2=“com”
string3=“www.hy”
string4=“www.hq”
expr match $string $string2 #0
expr match $string $string3 #0
expr match $string $string4 #6

expr substr

string=“www.hqyj.com.hqyj.com.qwer”
expr substr $string 5 4 #hqyj
在string中截取从第5个字符开始,向后的4个字符

expr index

#提取指定字符的下标,单个字符有意义,如配置文件:
string=“my_file=/etc/passwd”
num=`expr index $string “=”`
file_path=${string:$num}
echo $file_path
tail -5 $file_path
#多个字符意义不大,如下说明
string=“www.hqyj.com.hqyj.com.qwer”
expr index $string “qy” #6
expr index $string “pqy” #6
拿p字符在string查找第一次出现的位置,如果
找到了就返回它在字符串中的下标,然后结束,
否者找不到接着拿q字符在string查找第一次位置
如果找到返回q在字符串中的下标,否则返回0

expr length

expr length $string
获取string变量字符串的长度 等价于 ${#string}

4. let

let 表达式1 表达式2 … 表达式n #中间用空格分隔

A=2
let C=$A*3
echo '$A*3='$C
let C=A*3
echo 'A*3='$C

输出:
在这里插入图片描述

  • 注:
    1. let必须是完整的算术表达式,即有等号两边
      let C=A+B 正确
      C=`let A+B` 错误
    1. let会运算所有的表达式
      VAR1=30
      VAR2=25
      let RET=VAR1+VAR2 RET=RET+VAR1
      echo $RET #85
    1. let中变量可以加$,也可以不加$
    1. 运算符的前后不能加空格,以空格分隔多个表达式

以下为错误用法:
① 运算符加空格报错

A=2
let C=$A * 3
echo '$A*3='$C

在这里插入图片描述
② 非完整算数运算表达式

 A=2
 C=let $A*3
 echo $C   

在这里插入图片描述

  • 48
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值