【Linux】Shell脚本

本文详细介绍了Shell编程的基础知识,包括Shell概述、输入输出处理、分支控制(算术表达式、逻辑判断、if/case分支)、循环控制(for/while/select)、函数定义及使用。涵盖了Shell脚本的关键元素,有助于初学者入门和进阶。
摘要由CSDN通过智能技术生成

目录

一、Shell概述

二、输入输出

三、分支控制

1. 表达式

2. if 分支

3. case 分支

四、循环控制

1. for 循环

2. while 循环

3. select 循环

五、函数


一、Shell概述

Shell是Linux系统连接用户和操作系统的外壳程序,将用户的输入和请求选择性传递给操作系统,然后处理来自操作系统的结果输出,简单来说Shell就是一个用户和操作系统之间的命令解释器。

Shell是一个外壳程序,同时也是一个脚本语言。

Shell脚本本质上是Linux命令,一条一条命令组合在一起,实现某一个功能,就形成了Shell脚本。

最常用的Shell是Bash(/bin/bash),是大多数Linux系统默认的Shell环境。

shell编程注意事项

  • shell文件通常以后缀 .sh 结尾;
  • 不能使用特殊符号,有严格的空格控制;
  • shell文件以 #!/bin/bash 开头
  • shell脚本变量命名规则与C语言一样

二、输入输出

Shell脚本语言只有一种数据类型,就是字符类型,即所有变量的类型都是字符,输入和输出的都是字符。

Shell变量分为用户变量环境变量系统变量,环境变量分为用户级、系统级和脚本级,用户级变量重启Shell外壳就会自动清除,系统变量用于实现某一个功能而存在。

变量的可用 = 进行赋值创建,用 $ 获取变量值,用 unset 清除变量。

# Shell常见的环境变量:

PATH  		命令所示路径,以冒号为分割;
HOME  		打印用户家目录;
SHELL 		显示当前Shell类型;
USER  		打印当前用户名;
ID    		打印当前用户id信息;
PWD   		显示当前所在路径;
TERM  		打印当前终端类型;
HOSTNAME    显示当前主机名;
PS1         定义主机命令提示符的;
HISTSIZE    历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间;
RANDOM      随机生成一个 0 至 32767 的整数;
HOSTNAME    主机名
# Shell常见的系统变量:

$0 		当前脚本的名称;
$n 		当前脚本的第n个参数,n=1,2,…9;
$* 		当前脚本的所有参数(不包括程序本身);
$# 		当前脚本的参数个数(不包括程序本身);
$? 		令或程序执行完后的状态,返回0表示执行成功;
$$ 		程序本身的PID号。

变量也可通过 read 进行键盘输入赋值,通过 echo 输出。

在使用 read 输入数据时,可配合 echo 使用进行输出提示,如 echo 提示字符串; read 变量 ,也可直接使用 read -p 提示字符串 变量 进行输入提示

在用 $ 对变量取值时,为了其他字符串对变量的影响,可用 { } 跟在 $ 后面将变量括起来。

#!/bin/bash

# 颜色输出格式 echo -e "\033[(显示方式);(字体色);(背景色)m(输入内容)\033[0m"
testStr1="hello world!\n"
echo $testStr1

# 显示方式:
# 1 粗体高亮
# 4 下划线
# 5 闪烁
# 8 隐藏

# 字体颜色:
# 31 红色
# 32 绿色
# 33 黄色
# 34 蓝色
# 35 紫色
# 36 天蓝
# 37 白色

# 背景颜色:
# 41 红色
# 42 绿色
# 43 黄色
# 44 蓝色
# 45 紫色
# 46 天蓝
# 47 白色

echo "请输入一个测试字符串:"; read testStr2
echo -e "\033[1;31;46m$testStr2\033[0m"
# 最后的0表示恢复默认系统输出默认设置

# echo 加上 -e 选项之后支持转移字符:
# \n 回车换行
# \r 回车
# \v 换行
# \t Tab制表符距离
# \c 在字符串输入末尾不换行

echo -e "请输入一个测试字符串:\c"; read testStr3
echo -e "\033[4;33;42m$testStr3\033[0m"

#echo 加上 -n 选项,输出不换行
read -p "请输入一个测试字符串:" testStr4
echo -e -n "\033[5;35;41m${testStr4}\033[0m"

三、分支控制

1. 表达式

Shell脚本中的表达式分为算术表达式逻辑表达式,算术表达式常用 let 进行赋值和计算,也可以用 ((表达式)) 双小括号进行算术表达式的赋值和计算。

除了Shell自身的算术表达式处理方式,还可以通过下载 bc 工具进行处理,也可用通过Shell脚本将字符串通过管道 | 传递给bc工具,让bc工具进行计算

逻辑表达式常用 test 命令进行逻辑判断,test命令的退出码为0表示逻辑为true,否则为false,通常在test命令的后面跟上 echo $? 语句显示test命令的判断结果。

test命令在进行判断的时候,= 两边都需要空一格。

test命令可用 [ ] 中括号进行等价替换,注意 [] 前后中括号之间都要有空格。

#!/bin/bash

echo "算术计算:"
a=1
b=2
let c=$a+$b
echo $c

((d=($a+$b)*$c))
echo $d
echo $(($c/$b))

yum install -y bc
echo "$c/$b" | bc
echo "scale=2;$c/$b" | bc
# bc工具通过scale指定精度

echo "逻辑判断:"
test $a = $b; echo $?
test $c = $(($a+$b)); echo $?

# 复合条件判断
# -gt 大于,greater than
# -lt 小于,less than
# -ge 大于等于,greater or equal
# -le 小于等于,less or equal
# -eq 数值等于,equal
# -a  与,可用&&替换,and
# -o  或,可用||替换,or

echo "复合条件判断:"
age=15
test $age -gt 10 -a $age -lt 20; echo $?
test $age -lt 10 -o $age -gt 20; echo $?

[ $age -gt 10 ] && [ $age -lt 20 ]; echo $?
[ $age -le 10 ] || [ $age -ge 20 ]; echo $?

# 文件和目录属性判断:
# -e 判断文件或目录是否存在
# -f 判断是否为文件以及是否存在
# -d 判断是否为目录以及是否存在
# -r -w -x 判断权限

chmod u-x _02_expression.sh
[ -r _02_expression.sh ]; echo $?
[ -w _02_expression.sh ]; echo $?
[ -x _02_expression.sh ]; echo $?
chmod u+x _02_expression.sh

2. if 分支

逻辑判断语句通常会搭配 if 条件分支控制语句使用,if条件控制语句有单分支、双分支和多分支三种不同的格式。

#!/bin/bash

# 单分支格式
if [ -f _01_hello.sh ]; then
	echo "01FILE EXIST!"
fi

# 双分支格式
if [ -f _02_hello.sh ]; then
	echo "02FILE EXIST!"
else
	echo "02FILE NOT EXIST!"
fi

# 多分支格式
if [ -d _01_hello.sh ]; then
	echo "01DIR EXIST!"
elif [ -f _01_hello.sh ]; then
	echo "01FILE EXIST!"
else
	echo "01FILE 01DIR NOT EXITS"
fi

# 判断crond进程是否正常运行
name=crond
num=$(ps -ef|grep $name|grep -vc grep)
if [ $num -eq 1 ];then
    echo "$num running!"
else
    echo "$num is not running!"
fi

3. case 分支

case 变量值 in
模式 1)
	命令序列1;;
模式 2)
	命令序列2;;
	.......
*)
	默认命令序列;;
esac

case值得注意的特点:

  • case行尾必须为单词"in",每一模式必须以右括号“)”结束
  • 双分号";;"表示命令序列结束
  • 模式字符串中,可以用方括号表示一个连续的范围,如"[0-9]";还可以用管道符号" | “表示或,如"A|B”
  • 最后的 " *) " 表示默认模式,其中的 星号 相当于通配符
#!/bin/bash

read -p "请输入一个字符:" input

case "$input" in
[a-z]|[A-Z])
	echo "您输入的是一个字母";;
[0-9])
	echo "您输入的是一个数字";;
*)
	echo "您输入的是一个空格、功能键或其他按键";;
esac

四、循环控制

1. for 循环

for val in valuelist...
do
    commands
done

for((exp1;exp2;exp3))
do
    commands
done
# exp1 初始化
# exp2 变量取值范围
# exp3 变量增量
#!/bin/bash

for i in {1..5};
do
	echo -e "\033[${i}mhello world\033[0m"
done


for i in 1 3 5;
do
	for j in 31 33 35 37;
	do
		echo -e "\033[${i};${j}mhello world\033[0m"
	done
done

2. while 循环

while 条件判断
do
    command
    ...
done
 
# while后面的命令执行成功则循环,否则跳出循环
#!/bin/bash

count=3
while [ $count -ge 0 ] 
do
    echo $count
    let count=$count-1
done

count=3
while (($count >= 0))
do
    echo $count
    ((count--))
done


# 通过while实现shell脚本给文件内容添加行号
if [ -f $1 ]; then
    i=1
    cat $1 | while read text
    do
        echo "$i:$text"
        ((i++))
    done
else
    echo "文件不存在"
fi

3. select 循环

select var in menu...
do
    commands
done
 
# select 后面跟的是菜单
# in 关键字后面是菜单取值列表
# 这些值以空格隔开
# 用户选择数字对应菜单值
# 变量var获取值后执行循环一次
#!/bin/bash

PS3="Please Select[1-4]"

select m in one two three four exit;
do
    if [ $m = exit ]; then
        break
    fi
    echo $m
done

# PS3是一个环境变量,是select的提示符

五、函数

Shell的函数定义与C语言类似,需要先定义再调用原则,函数名后面接小括号,可以有参数或返回值,但是没有返回值类型。

#shell中的函数定义
#其中function为关键字,FUNCTION_NAME为函数名
function FUNCTION_NAME(){
       command1 #函数体中可以有多个语句,不允许有空语句
       command2
       ...
}
#省略关键字function,效果一致
FUNCTION_NAME(){
       command1
       command2
       ...
}
 
# 函数名后的小括号中没有参数
# 函数function关键字可以不写
# 函数必须遵循先定义再调用原则
#!/bin/bash
 
echo -n "请输入文件名:"
read FILE
function checkFileExist(){
        if [ -f $FILE ]; then
                return 0
        else
                return 1
        fi
}
 
echo "call function checkFileExist"
checkFileExist
if [ $? -eq 0 ]; then
        echo "$FILE exist"
else
        echo "$FILE not exist"
fi
#!/bin/bash

Hello(){
    echo "hello world"
}

Hello

# 写一个函数判断文件是否存在 
function CheckFileExist(){
    if [ -f $1 ]; then
        return 0
    else
        return 1
    fi
}

read -p "请输入文件名:" filename
CheckFileExist $filename

if [ $? -eq 0 ]; then
    echo "$filename is exits!"
else
    echo "$filename is not exits!"
fi

由于Shell是一门面向过程的脚本型语言,而且用户主要是Linux系统管理人员,所以并没有非常活跃的社区,这也造成了Shell缺乏第三方函数库,所以在很多时候需要系统管理人员根据实际工作的需要自行开发函数库。下面建立一个叫 funclib 的函数库,该函数库目前只有一个函数,用于判断文件是否存在。

_checkFileExists(){
      if [ -f $1 ]; then
             echo "File:$1 exists"
      else
             echo "File:$1 not exist"
      fi
}

其他脚本在希望直接调用_checkFileExists函数时,可以通过直接加载 funclib 函数库的方式实现。加载方式有如下两种:

#使用“点”命令
$ . /PATH/TO/LIB

#使用source命令
$ source /PATH/TO/LIB

假设现在有个脚本想要直接调用_checkFileExists函数,可以通过加载 funclib 函数库来实现。

可以通过 set unset 命令查看当前内存中已经定义和载入的函数,使用 unset 清除函数,函数修改后必须重新载入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllinTome

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值