shell脚本基础知识汇总

本文详细介绍了Shell脚本的执行方式,包括bash和sh解析器的使用。讲解了如何修改环境变量,特别是PATH路径,并探讨了不同级别的生效范围。此外,文章还涵盖了变量的声明与访问、数组操作、输入输出命令如echo和read,以及算术运算的不同方法。同时,它还讨论了条件测试(test)和分支结构(if)的使用,以及循环结构(while、for)和函数的创建。
摘要由CSDN通过智能技术生成

1、执行脚本的方式

#!/bin/bash

echo hello world

bash 文件名 解析脚本

  • bash会在后台打开一个终端,将结果返回到当前终端

source 文件名 读取脚本信息,并运行

  • 在当前终端解析脚本,并把结果返回给当前终端

chmod 777 文件名 给脚本赋予可执行权限

2、shell常用的解析器

  1. bash,与终端交互性比较好,多用于Linux系统
  2. sh,与终端交互性较好,一般用于开发板

3、修改环境变量

env终端输入直接查看系统变量

echo $PATH PATH的作用,包含了执行文件时的默认查找路径,如果文件不在默认查找路径中,就需要添加上路径,比如./a.out

4、修改PATH路径

该PATH过程中不要对原有的路径进行修改

4.1 只对当前终端生效

export PATH=$PATH:/home/ubuntu

export 给系统变量赋值

4.2 只对当前用户生效

修改家目录下的.bashrc文件

sudo vim ~/.bashrc

在文件的最下方,添加一条export表达式

export PATH=$PATH:/home/ubuntu

让配置文件生效:

  1. 重启,永久生效
  2. source ~/.bashrc
  3. . ~/.bashrc(后两种方式都只能临时生效)

4.3 对所有用户生效

sudo vim /etc/bash.bashrc

在文件的最下方,添加一条export表达式

export PATH=$PATH:/home/ubuntu/test

让配置文件生效:

  1. 重启,永久生效
  2. source /etc/bash.bashrc
  3. . /etc/bash.bashrc(后两种方式都只能临时生效)

另一种方法

修改/etc/environment,把路径添加到原有内容后面

让配置文件生效:

  1. 重启,永久生效
  2. source /etc/environment
  3. . /etc/environment(后两种方式都只能临时生效)

5、shell中的变量

shell中默认都是全局变量

变量名=变量的值

变量名=‘变量的值’

变量名=”变量的值“

注意事项

  1. = 两边不允许有空格
  2. 变量的中间值,加空格时,需要使用 ’ ’ 或者 " "
  3. shell中访问不存在的变量,结果为空值

5.1 访问变量的方式

$变量名 或者 ${变量名}

5.2 修饰变量的关键字

unset		#清空变量
readonly	#只读变量,不能修改
local		#定义局部变量,只能在函数中使用

5.3 位置变量/外部传参

echo $0 $1 $2 $3 ... $n
echo $*		#$*获取外部的所有参数,不包括脚本名
echo $@		#$@获取外部的所有参数,不包括脚本名
echo $#		#$#获取外部参数的个数,不包括脚本名

6、命令置换符

  • 把指令运行的结果值给变量

    1.``

    2.$()

7、数组

数组名=(初值1 初值2 初值3 ...)

  • shell中的数组,用**( )**进行初始化,每一个初始值之间存的是空格

数组名=([下标]=初值1 [下标]=初值2 [下标]=初值3 ...)

  • 稀疏数组的下标可以不连续
  • 数组成员的赋值数组名[下标]=90

${数组名[下标]}

  • 访问数组中的元素

${#arr[*]} 或者 ${#arr[@]}

  • 获取数组中元素的个数

${arr[@]} 或者 ${arr[*]}

  • 访问数组内所有元素

8、输入和输出

8.1 echo

echo打印是会自动换行,且不解析转义字符

echo -n 取消打印时的换行

echo -e "1\n"加**-e**可以解析转义字符

8.2 read

read 变量名从终端读取变量

read -s 变量名不会回显从终端输入的变量

read -p "提示信息" 变量名终端1读入前输出提示信息

read -t 秒数 变量名终端输入等待的秒数

read -n 参数个数 变量名指定个数字符输入

read -a 数组名从终端输入数组中的元素

9、算术运算

9.1 (())

  • 常用于shell中的整数运算

  • (())几乎支持所有C语言中的复杂运算,支持幂运算(**)

  • (())使用数据时,可以加**$**也可以不加

  • (())使用数据运算时,运算符两侧可以加空格

  • ((表达式1, 表达式2, 表达式3....))每个表达式都会运行取最后一个表达式的结果

9.2 let

  • let 变量名=表达式
  • let使用变量时,可以加**$**也可以不加
  • let在进行运算时,运算符两侧不允许加空格let var=a+b
  • let支持幂运算(**)和自增(++)自减(–)

9.3 $[]

  • 变量名=$[表达式1, 表达式2, 表达式3...]每个表达式都执行,取最后一个表达式的结果
  • 使用变量可以加**$**也可以不加
  • 运算符两侧可以有空格也可以没有
  • 支持幂运算(**)和自增(++)自减(–)

9.4 expr

  • expr是一条指令
  • expr在运算时,必须给变量加**$**
  • 运算符两侧必须有空格
  • 不支持幂运算和自增自减
  • 使用时某些字符需要转义
  • 接收expr的数据使用**``**
  • match STRING1 STRING2
    • 返回string2在string1中匹配的个数
  • substr STRING POS LENGTH
    • 返回从string中第pos个位置开始,截取length长度的字符串
  • index STRING CHARS
    • 返回字符在字符串第一次出现的位置,从位置1开始,如果查找的是多个字符,返回第一次出现的字符位置
  • length STRING
    • 返回字符串长度
  • expr的基础算术语法
  ARG1 | ARG2       若ARG1的值不为0,则返回ARG1,否则返回ARG2
 
  ARG1 & ARG2       若两边的值都不为0,则返回ARG1,否则返回 0 
 
  ARG1 < ARG2       ARG1 小于ARG2
  ARG1 <= ARG2      ARG1 小于或等于ARG2
  ARG1 = ARG2       ARG1 等于ARG2
  ARG1 != ARG2      ARG1 不等于ARG2
  ARG1 >= ARG2      ARG1 大于或等于ARG2
  ARG1 > ARG2       ARG1 大于ARG2
 
  ARG1 + ARG2       计算 ARG1 与ARG2 相加之和
  ARG1 - ARG2       计算 ARG1 与ARG2 相减之差
 
  ARG1 * ARG2       计算 ARG1 与ARG2 相乘之积
  ARG1 / ARG2       计算 ARG1 与ARG2 相除之商
  ARG1 % ARG2       计算 ARG1 与ARG2 相除之余数
  • expr对字符串的惭怍
match STRING1  STRING2
    返回string2在string1中完全匹配的个数
   

substr STRING POS LENGTH
    返回从string中的第pos个位置开始,截取length长度的子串

index STRING CHARS
    返回字符在字符串中第一次出现的位置,位置从1开始,如果查找的是多个字符,返回的是最小的weizhi 

length STRING
    返回字符串的长度

将网址分段放入数组

#!/bin/bash
arr=()
i=0
read -p "输入一个网址:" str

#str=www.4399.com
len1=`expr length $str`
head1=`expr index $str .`
arr[$i]=`expr substr $str 1 $[head1-1]`
#arr[1]=www

#str2=4399.com
str2=`expr substr $str $[head1+1] $[len1-head1+1]`
echo $str2
head2=`expr index $str2 .`
len2=`expr length $str2`
arr[$[++i]]=`expr substr $str2 1 $[head2-1]`
arr[$[++i]]=`expr substr $str2 $[head2+1] $[len2-head2]`
echo ${arr[*]}

10、分支结构

10.1 test

#整数运算
a = b	a -eq b
a >= b	a -ge b
a > b	a -gt b
a <= b	a -le b
a < b	a -lt b
a != b	a -ne b
#对字符串操作 在if中使用字符串判断,给字符串加上双引号

     -n STRING   #判断字符串是否非空 
                 #the length of STRING is nonzero

       			 #STRING equivalent to -n STRING

     -z STRING   #判断字符串是否为空 
                 #the length of STRING is zero
 
     STRING1 = STRING2   #判断字符串是否相等 
                           #the strings are equal

     STRING1 != STRING2   #判断字符串是否不相等 
                            #the strings are not equal
#对文件的相关操作
-r:文件存在并且可读
-w:文件存在并且可写
-x:文件存在并可执行
-s:文件存在并且有内容
-S:文件存在且为套接字文件
-b:文件存在且为块设备文件
-p:文件存在且为管道文件
-L/-h:文件存在且为软链接文件
-f:文件存在并为普通文件
-e:文件存在
file1 -nt file2:1的时间戳比2更新
file1 -ot file2:1的时间戳比2的更旧/2的时间戳更新

10.2 if

#单分支if
if [ test语句 ]
then
	
	语句块
	
fi

#双分支if
if [ test语句 ]
then
	
	语句块

else

	条件不成立执行的语句

fi

#多分支if
if [ test语句 ]
then
	
	语句块

elif
then

	条件不成立执行的语句

fi

输入一个文件名,判断是否为shell脚本文件,如果是脚本文件,判断是否有可执行权限,如果有可执行权限,运行文件,如果没有可执行权限,给文件添加可执行权限。

#!/bin/bash
read -p "请输入文件名:" filename

len=`expr length $filename`
head=`expr index $filename .`
tail=`expr substr $filename $[head+1] $[len-head]`

if [ $tail = "sh" ]
then
	if [ -x $filename ]
	then
		bash $filename

	else
		chmod 777 $filename
	fi

else
	echo 不是脚本
fi

终端输入两文件名,判断哪一个文件更新

#!/bin/bash
read -p "请输入文件名:" filename1
read -p "请输入文件名:" filename2

if [ $filename1 -nt $filename2 ]
then
	echo $filename1更新
	
else
	echo $filename2更新
fi

终端输入用户,判断用户是否存在,如果不存在,添加用户

#!/bin/bash
read -p "输入一个用户名:" name

usrname=`grep ^$name /etc/passwd `
if [ $usrname ]
then
	echo 存在此用户
else
	sudo adduser $name
fi

终端输入年份,判断闰平年

#!/bin/bash
read -p "输入一个年份:" year
if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]
then
	echo "$year是闰年"
else
	echo "$year是平年"
fi

10.3 case … in

case ${变量名} in
	常量)
		语句
		;;
	常量)
		语句
		;;
	.....
	常量n)
		语句
esac
#!/bin/bash
read -p "请输入一个变量" var
case $var in
		a)
			echo "a"
			;;
		b)
			echo "b"
			;;
*)		#*的功能类似c中的default,defaul的位置可以任意
		#*表示通配所有情况,位置不能任意
			echo "其他情况"
			;;
		c)
			echo "c"
			#;;	最后一个分支可以不加;;
			
esac

1|2|3|4):符合1-4任一个即可
[1-4][8-9]):符合1-4,和8-9中任一个即可
[0-9]):符合0-9中任一个即可
1):符合1

11、通配符

  • *:通配一个或多个字符
  • ?:通配一个字符
  • []:只能通配[]中的一个字符
  • [1-5]:通配1-5内的任意一个字符
  • [12345]:通配12345中的任一个字符
  • [1,2,3,4,5]:通配方括号中的所有内容

终端输入年分,输出每个月各有多少天

#!/bin/bash
read -p "输入一个年份:" year
read -p "输入一个月份:" month

case $month in
	1|3|5|7|8|10|12)
		echo "这个月31天"
		;;

	4|6|9|11)
		echo "这个月30天"
		;;

	2)

		if [ $((year%4)) -eq 0 -a $((year%100)) -ne 0 -o $((year%400)) -eq 0 ]
		then
			echo "这个月29天"
		else
			echo "这个月28天"
fi

esac

12、循环结构

12.1 while

while [ 条件 ]
do
	语句块
done
#!/bin/bash
read var
i=1
j=1
while [ $i -le $var ]
do
	j=1
	while [ $j -le $i ]
	do
		echo -n "*"
		((j++))
	done
	echo
	((i++))
done

12.2 for

#for语句的三种表达方式
for((表达式1, 表达式2, 表达式3))
do
	语句块
	
done

for 变量名 in 字符串列表
do
	语句块
done
执行逻辑:
	var变量会循环得到字符串列表,a、b、c、d每一个值,并在赋值结束后进入循环,当每一个字符串都被赋值一次后,退出循环
!#/bin/bash
#求1-100的和
sum=0    #记录求和的结果 
#for((i=0;i<=100;i++))
#for i in `seq 1 1 100`
for i in {1..100} 
do((sum+=i)) 
done 
echo $sum
#稀疏数组求和
#!/bin/bash
arr=([0]=90 [3]=100 [7]80)
sum=0
for sum1 in ${arr[*]}
do
	((sum+=arr))
done
echo $sum
#判断家目录下的目录文件和普通文件数量
#!/bin/bash
f=0
d=0

for filename in `ls ~ -a`
do
	if [ -f ~/$filename ]
	then
		((f++))
	fi
	if [ -d ~/$filename ]
	then
		((d++))
	fi

done
echo $f
echo $d

12.3 select…in

select 变量名 in  选项列表
do
    语句块
done
 
执行逻辑:
    打印选项列表让用户通过数字选择
1) aa
2) bb
3) c
#? 
如果用户不输入,会再打印一次提示的选项列表
ctrl+c结束选项
#!/bin/bash 
select var in unix linux wins
docase $var in 
		unix) 
			echo "打开的是unix系统" 
			;; 
		linux) 
			echo "打开的linix系统" 
			;; 
		wins) 
			echo "打开的是wins系统" 
			;;esac


done 

12.4 辅助控制关键字

  • break
    • break n可以跳出n层循环
    • break默认跳出1层循环
  • continue
    • continue n可以跳出n层本次循环
    • continue默认跳出一层本次循环

13、函数

function 函数名() 	括号中不能放内容
{
	函数体
	return 返回值
}
  • shell函数定义可以加function,也可以不加
  • 函数是否有参数,根据调用的形式和函数的实现有关
  • 函数是否有返回值,要看具体的函数如何实现
  • shell中函数需要先定义后调用,shell中没有函数声明
    • 函数名 参数1 参数2 参数3 ...函数调用
  • 函数内通过位置参数接收参数
    • $1 $2 ... ${n}
  • 函数参数和脚本参数互不影响
    • 函数内部使用位置变量,接收的是函数参数
    • 函数外部使用位置变量,接收的是脚本参数
    • $0只能是脚本名
  • 函数返回值只能是**[0-255]**之间的数
    • 如果函数需要返回值,只需要在函数内写return
    • echo $?可以用于接收函数返回值
      • **$?**本质是上一条指令的执行结果
  • local只能在函数中使用
#函数数组求和
#!/bin/bash
sum=0
function fun()
{
	for((i=0; i<len; i++))
	do
		((sum+=${arr[i]}))
	done
}

arr=([0]=50 [1]=70 [2]=80)
len=${#arr[*]}
fun ${arr[*]} len

echo $sum
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值