这是我在学习shell脚本时整理的常见练习题,大家可按照顺序来练习,语法都是从前往后逐渐递进的,另外看不懂的建议用AI分析,希望对大家有帮助!
目录
2.编写脚本,判断当前的系统剩余内存的大小,如果小于 600M 则输出信息到日志文件中
4.判断光盘是否挂载,如果挂载则显示挂载目录下的内容,否则执行挂载命令
5.判断本地仓库是否创建,如果创建则显示已创建,否则创建这个本地仓库文件。
6.判断 sshd 进程是否运行,如果服务未启动则启动相应服务。
10.由用户从键盘输入一个字符,判断该字符是字母还是数字,以及其他字符,并输出相应的提示信息。
21.使用 exec 读取指定文件的内容并循环输出。文件的内容如下
25.用until实现将之前使用 for 循环语句创建的 test01 - test30 用户删除
27.用select实现选择水果,假设我们有如下水果可供选择:
35.写一个脚本,判断给定的 IP 地址范围[192.168.72.130 ~ 192.168.72.140]是否在线。
38.编写一个bash脚本以输出一个文本文件mywords.txt中第5行的内容。
39.使用函数递归/var/log目录,如果是文件直接输入文件名,如果是目录则输出目录名称并输出目录下所有子目录和文件名
41.从标准输入读取 n 次字符串,每次输入的字符串保存在数组 array 中。
45.写一个bash脚本以统计一个文本文件nowcoder.txt 中每个单词出现的个数。
1.判断是否已经成功挂载光盘,如果挂载则显示光盘中的文件
#!/bin/bash
# 获取 /mnt 目录下文件列表的行数
num=$(ls -l /mnt | grep "total" | cut -d" " -f2)
# 判断行数是否为 0,如果是则说明光盘未挂载
if [ $num -eq 0 ] ; then
echo 'no mount'
else
# 显示 /mnt 目录中的文件列表
ls -l /mnt
fi
2.编写脚本,判断当前的系统剩余内存的大小,如果小于 600M 则输出信息到日志文件中
#!/bin/bash
# 1.使用 free 命令获取系统内存信息,
2.然后使用 grep 命令过滤出包含 "Mem:" 的行,
3.再使用 tr 命令将连续的空格字符压缩为单个空格字符,
4.最后使用 cut 命令提取第 4 列的剩余内存值(以兆字节为单位)并赋值给变量 free_mem
free_mem=$(free -m | grep "Mem:" | tr -s " " | cut -d " " -f4)
# 检查剩余内存是否小于 600 兆字节
if [ $free_mem -lt 600 ]; then
# 如果剩余内存小于 600 兆字节,则记录日志
logger "free mem less 600M"
fi
3.编写脚本,判断当前脚本的执行者是否为 root 用户
#!/bin/bash
# 检查当前登录用户是否为 root 用户
# 如果不是 root 用户,则输出提示信息
if [ $USER != "root" ]; then
echo "Use root to login"
fi
4.判断光盘是否挂载,如果挂载则显示挂载目录下的内容,否则执行挂载命令
#!/bin/bash
# 获取 /mnt 目录下以 "总用量" 开头的文件的第二列的值,并将其赋给 number 变量
number=$(ls /mnt | grep "总用量" | cut -d " " -f2)
# 检查 number 变量是否为 0
if [[ $number -eq 0 ]]; then
# 如果 number 变量为 0,则将光盘挂载到 /mnt 目录下
mount /dev/sr0 /mnt
else
# 如果 number 变量不为 0,则列出 /mnt 目录下的文件列表
ls /mnt
fi
5.判断本地仓库是否创建,如果创建则显示已创建,否则创建这个本地仓库文件。
#!/bin/bash
# 通过判断所有仓库中是否存在baseurl=/mnt的项,来认定本地仓存是否存在
# 使用 cat 命令读取所有仓库配置文件,并通过 grep、tail 和 cut 命令获取最后一个仓库的 baseurl 内容
res=$(cat /etc/yum.repos.d/*.repo | grep "baseurl" | tail -1 | cut -d"=" -f2)
# 检查获取到的 baseurl 是否为 /mnt
if [ "$res" == "/mnt" ]; then
echo "Local repository already exists."
else
echo "Creating local repository..."
# 使用 cat 命令将 YUM 仓库配置写入到 yum.repo 文件
/usr/bin/cat > /etc/yum.repos.d/yum.repo << "EOF"
[baseOS]
name=baseOS
baseurl=/mnt
gpgcheck=0
EOF
echo "Local repository created successfully."
fi
6.判断 sshd 进程是否运行,如果服务未启动则启动相应服务。
方式一:服务状态实现
#!/bin/bash
# 检查sshd服务的状态
sshd_status=$(systemctl is-active sshd)
# 如果sshd服务处于活跃状态
if [ "$sshd_status" == "active" ]; then
echo "sshd已激活"
else
# 如果sshd服务未激活,则启动它
echo "sshd未激活"
systemctl start sshd
echo "sshd已启动"
fi
方式二:
#!/bin/bash
# 通过检查网络状态,查看端口22是否在使用,以确定sshd是否正在运行
sshd_port_count=$(netstat -lnput | grep 22 | wc -l)
# 如果在端口22上找到相关的网络活动,表示sshd正在运行
if [ $sshd_port_count -gt 0 ]; then
echo "sshd已激活"
else
# 如果未找到端口22上的活动,表示sshd可能没有运行,需要启动
echo "sshd未激活"
systemctl start sshd # 尝试启动sshd服务
echo "sshd已启动"
fi
7.检查主机是否存活,并输出结果
#!/bin/bash
# 定义要 ping 的主机 IP 地址
host="192.168.145.146"
# 使用 ping 命令发送 3 个数据包到指定的主机 IP,设置超时时间为 1 秒,并将所有输出重定向到 /dev/null(即丢弃输出)
ping -c 3 -W 1 $host &> /dev/null
# 检查 ping 命令的退出状态码($?)是否为 0,如果是则表示主机可达,否则表示不可达
if [ $? -eq 0 ]; then
echo "$host is active" # 输出主机活跃的消息
else
echo "$host is not active" # 输出主机不活跃的消息
fi
8.接收两个整数并比较其大小。
方式一:read实现
#!/bin/bash
# 提示用户输入两个数字,并将输入的数字保存到变量 num1 和 num2 中
read -p "please input two numbers: " num1 num2
# 使用 if-elif-else 结构比较输入的两个数字
if [ $num1 -eq $num2 ]; then # 检查 num1 是否等于 num2
echo "$num1 == $num2" # 如果相等,则输出相等的消息
elif [ $num1 -gt $num2 ]; then # 如果 num1 大于 num2
echo "$num1 > $num2" # 则输出 num1 大于 num2 的消息
elif [ $num1 -lt $num2 ]; then # 如果 num1 小于 num2
echo "$num1 < $num2" # 则输出 num1 小于 num2 的消息
else # 如果以上条件都不满足
echo "number error" # 则输出数字错误的消息
fi
方式二:脚本传参实现
#!/bin/bash
# 检查脚本是否接收了两个参数
if [ $1 -eq $2 ]; then # 检查第一个参数是否等于第二个参数
echo "$1 == $2" # 如果相等,则输出相等的消息
elif [ $1 -gt $2 ]; then # 如果第一个参数大于第二个参数
echo "$1 > $2" # 则输出第一个参数大于第二个参数的消息
elif [ $1 -lt $2 ]; then # 如果第一个参数小于第二个参数
echo "$1 < $2" # 则输出第一个参数小于第二个参数的消息
else # 如果以上条件都不满足
echo "error" # 则输出错误消息
fi
9.根据用户的输入成绩,判断优良中差。
85-100 为优,A
70-84 为良,B
60-69 为合格,C
60以下为不合格,D
方式一:[[ ]]结合&&,||实现
#!/bin/bash
# 提示用户输入成绩并保存到变量score中
read -p "input score:" score
# 检查分数是否为空
if [[ -z $score ]]; then
echo "the score is not empty"
exit 1
# 检查分数是否在有效范围内(0到100之间)
elif [[ $score -gt 100 || $score -lt 0 ]];then
echo "the score should be between 0 and 100, please input a correct score"
exit 2
# 判断成绩所属等级并输出对应的评语
elif [[ $score -ge 85 && $score -le 100 ]]; then
echo "A 优"
elif [[ $score -ge 70 && $score -le 84 ]]; then
echo "B 良"
elif [[ $score -ge 60 && $score -le 69 ]]; then
echo "C 合格"
else
echo "D 不合格"
fi
方式二:[ ]结合-a,-o实现
#!/bin/bash
# 提示用户输入成绩并保存到变量score中
read -p "input score:" score
# 检查分数是否为空
if [ -z $score ]; then
echo "the score is not empty"
exit 1
# 检查分数是否在有效范围内(0到100之间)
elif [ $score -gt 100 -o $score -lt 0 ];then
echo "the score should be between 0 and 100, please input a correct score"
exit 2
# 根据分数判断等级并输出对应的评语
elif [ $score -ge 85 -a $score -le 100 ]; then
echo "A 优"
elif [ $score -ge 70 -a $score -le 84 ]; then
echo "B 良"
elif [ $score -ge 60 -a $score -le 69 ]; then
echo "C 合格"
else
echo "D 不合格"
fi
10.由用户从键盘输入一个字符,判断该字符是字母还是数字,以及其他字符,并输出相应的提示信息。
#!/bin/bash
# 提示用户输入一个字符并保存到变量key中
read -p "input a key:" key
# 检查输入是否为空
if [ -z $key ]; then
echo "not null"
exit 1
fi
# 检查输入字符长度是否为1
if [ $(expr length $key) -ne 1 ]; then
echo "char must be one"
exit 2
fi
# 根据输入字符的类型进行分类并输出对应的信息
case $key in
[0-9])
echo "number"
;;
[a-z]|[A-Z])
echo "char"
;;
*)
echo "other"
;;
esac
11.9题用case实现
#!/bin/bash
# 提示用户输入一个分数并保存到变量score中
read -p "input score:" score
# 使用 case 语句根据分数范围输出对应的等级
case $score in
# 如果分数在 85 到 100 之间,输出 A
[8][5-9]|[9][0-9]|100)
echo "A"
;;
# 如果分数在 70 到 84 之间,输出 B
[7][0-9]|[8][0-4])
echo "B"
;;
# 如果分数在 60 到 69 之间,输出 C
[6][0-9])
echo "C"
;;
# 其他分数,输出 D
*)
echo "D"
esac
12.开发一个 rsync 起停脚本
#!/bin/bash
# 检查参数数量是否正确
if [ "$#" -ne 1 ]; then
echo "Usage: $0 {start|stop|restart}"
exit 0
fi
# 根据参数执行相应操作
case $1 in
"start")
# 启动rsync服务
/usr/bin/rsync --daemon
sleep 1
# 检查rsync服务是否成功启动
if [ $(ss -lntup | grep rsync | wc -l) -ge 1 ]; then
echo "rsync started"
exit 0
fi
;;
"stop")
# 停止rsync服务
killall rsync &>/dev/null
sleep 1
# 检查rsync服务是否成功停止
if [ $(ss -lntup | grep rsync | wc -l) -eq 0 ]; then
echo "rsync stopped"
exit 0
fi
;;
"restart")
# 重启rsync服务
if [ $(ss -lntup | grep rsync | wc -l) -ge 1 ]; then
killall rsync &>/dev/null
/usr/bin/rsync --daemon
sleep 1
echo "rsync restarted"
else
echo "rsync is not running, starting..."
/usr/bin/rsync --daemon
sleep 1
echo "rsync started"
fi
exit 0
;;
*)
# 参数错误提示
echo "Usage: $0 {start|stop|restart}"
exit 0
;;
esac
13.直接列出列表的所有元素
#!/bin/bash
# 这行指定了将执行此脚本的解释器,这里是bash。
# 循环遍历列表中的每个IP地址
for var in 192.168.132.130 192.168.132.131 192.168.132.132
do
# 打印当前的IP地址
echo $var
done
# 循环结束
改进版本1:通过{..}实现
#!/bin/bash
# 指定脚本解释器为bash
# 使用花括号扩展生成从192.168.132.130到192.168.132.132的IP地址列表
# {0..2} 表示从0到2的数字序列,会替换成列表中的每个数字
for var in 192.168.132.13{0..2}
do
# 打印当前的IP地址
echo $var
done
# 循环结束
改进版2:通过seq实现
#!/bin/bash
# 指定脚本解释器为bash
# 使用seq命令生成从0到2的数字序列,并利用格式字符串生成IP地址列表
# 这里的格式字符串 "192.168.132.13%1g" 中的 %1g 会被0到2的数字替换
# 生成的IP地址列表为:192.168.132.130、192.168.132.131、192.168.132.132
for var in `seq -f "192.168.132.13%1g" 0 2`
do
# 打印当前的IP地址
echo $var
done
# 循环结束
14.seq
# 生成一个带有格式的序列,使用 seq 命令
# -f 参数指定了格式字符串,这里的 %1g 表示按照给定的数字进行格式化
# 生成的序列为:192.168.132.130
seq -f "192.168.132.13%1g"
# 生成从 1 到 100 的数字序列,使用 seq 命令,并将数字以加号连接
# 然后使用 bc 命令计算这个序列的总和
seq -s"+" 1 100 | bc
# 使用 seq 命令生成一个序列,从 2 开始,以步长 2 递增,直到 100 结束,并用加号分隔
# 生成的序列为:2+4+6+...+98+100
seq -s"+" 2 2 100 |
# 将生成的序列传递给 bc 命令进行求和计算
bc
通过for实现100以内的偶数求和
#!/bin/bash
sum=0
for ((i=2;i<=100;i+=2))
do
let sum+=i
done
echo $sum
15.循环输出1-10中的奇数
#!/bin/bash
# 以上一行声明脚本解释器为 bash
# 使用for循环遍历从1到10的数字,步长为2,即遍历奇数
for var in {1..10..2}
do
# 打印当前迭代的数字
echo $var
done
16.获取根目录下所有文件名作为变量的值打印输出。
#!/bin/bash
# 以上一行声明脚本解释器为 bash
# 使用 for 循环遍历根目录下的所有目录
# `ls -F /`:列出根目录下的所有文件和目录,并在每个目录名称后面加上斜杠以区分目录和文件
# `grep "/$"`:过滤出以斜杠结尾的行,即目录行
for file in `ls -F / | grep "/$"`
do
# 打印每个目录的名称
echo $file
done
17.打印出如下的语句中字符数不大于6的单词。
hello world rabbit favorite eat apple cabbage
#!/bin/bash
# 以上一行声明脚本解释器为 bash
# 使用for循环遍历单词列表
for word in hello world rabbit favorite eat apple cabbage
do
# 判断单词的长度是否小于等于6
if [ `expr length $word` -le 6 ]; then
# 如果单词长度小于等于6,则打印该单词
echo $word
fi
done
18.循环输入所有的参数
#!/bin/bash
# 以上一行声明脚本解释器为 bash
# 使用for循环遍历命令行参数列表中的每个参数
for var in $@
do
# 打印每个参数的值
echo $var
done
19.批量创建用户
用户名以 test 开头,按数字序号变化。一共添加 30 个账号,名称如:test01、test02、...、test10、....test30
#!/bin/bash
# 循环创建用户
for ((i=1;i<=30;i++))
do
# 根据循环计数器 i 的值确定用户名
if [ $i -lt 10 ]; then
user=test0$i
else
user=test$i
fi
# 检查用户是否存在
if ! id -u $user &>/dev/null; then
# 如果用户不存在,则创建用户并设置密码
useradd $user
# 通过管道将密码 "Abc123456" 传递给 passwd 命令,用于为新创建的用户设置密码
echo "Abc123456" | passwd --stdin $user &>/dev/null
else
# 如果用户已存在,则输出提示信息
echo "$user already exists"
fi
done
方式二:通过seq实现
#!/bin/bash
# 循环遍历生成 test01 到 test30 的用户名
for u in `seq -f "test%02g" 1 30`
do
# 检查用户是否已存在
if ! id -u $u &>/dev/null; then
# 如果用户不存在,则创建用户
useradd $u
# 使用 echo 和管道将密码传递给 passwd 命令,并将标准输出和标准错误输出都重定向到 /dev/null,确保密码设置过程中的安全
echo "Abc123456" | passwd --stdin $u &>/dev/null
fi
done
20.循环输出 1~10这几个数
#!/bin/bash
# 设置初始变量 i 为 1
i=1
# 开始 while 循环,循环条件是 i 小于等于 10
while [ $i -le 10 ]
do
# 打印当前 i 的值
echo $i
# 将 i 的值加 1
let i++
done
21.使用 exec 读取指定文件的内容并循环输出。文件的内容如下
```bash
[root@openEuler ~]# cat myfile
open
openlab
openlab123
linux
readhat
```
方式一:
#!/bin/bash
# 将文件 "myfile" 的内容作为标准输入传递给脚本
exec < myfile
# 开始 while 循环,逐行读取文件中的内容
while read line
do
# 打印当前行的内容
echo $line
done
方式二:
#!/bin/bash
# 使用重定向将文件 "myfile" 的内容作为输入传递给 while 循环
while read line
do
# 打印当前行的内容
echo $line
done < myfile
22.猜商品价格。
通过变量 RANDOM 来获取随机的价格,然后提示用户猜价格,并记录次数,猜中退出,或次数达到 5 也退出。
#!/bin/bash
# 获取随机价格
random_price=$((RANDOM % 100 + 1)) # 生成1到100之间的随机数作为价格
# 记录次数
count=0
while :
do
# 提示用户输入
read -p "please input your price:" price
((price = price)) # 将输入的价格转换为数字格式
let count++ # 次数加1
# 判断是否猜中或次数达到五次退出
if [ $random_price -eq $price -o $count -ge 5 ]; then
break # 若猜中或者猜了五次,退出循环
elif [ $price -gt $random_price ]; then
echo "your price is high"
continue # 若价格过高,继续下一轮循环
else
echo "your price is low"
continue # 若价格过低,继续下一轮循环
fi
done
23.使用while读取文件,文件的内容如下
```
192.168.72.131 22
192.168.72.132 23
192.168.72.133 22
```执行输出的结果为:
```
IP: 192.168.72.131, PORT: 22
IP: 192.168.72.132, PORT: 23
IP: 192.168.72.133, PORT: 22
```
#!/bin/bash
# 从文件 ipf 逐行读取内容并处理
while read line
do
# 从每行内容中提取 IP 地址和端口号
IP=`echo $line | cut -d" " -f1`
PORT=`echo $line | cut -d" " -f2`
# 输出 IP 地址和端口号
echo "IP: $IP, PORT: $PORT"
done < ipf # 从文件 ipf 中读取数据
24.until循环输出0~10之间的数
#!/bin/bash
# 设置初始值为0
i=0
# 使用 until 循环,直到 i 大于 10 才结束
until [ $i -gt 10 ]
do
# 输出当前 i 的值
echo $i
# 将 i 值加1
let i+=1
done
这里 let i+=1<==>((i+=1))
25.用until实现将之前使用 for 循环语句创建的 test01 - test30 用户删除
#!/bin/bash
# 设置初始值为1
i=1
# 使用 until 循环,直到 i 大于 30 才结束
until [ $i -gt 30 ]
do
# 根据循环计数器 i 的值确定用户名
if [ $i -lt 10 ]; then
user=test0$i
else
user=test$i
fi
# 检查用户是否存在
if id -u $user &>/dev/null; then
# 如果用户存在,则删除
userdel -r $user
else
# 否则输出用户不存在
echo "$user does not exist"
fi
# 将 i 值加1
let i++
done
26.select实现mysql版本的选择
#!/bin/bash
# 使用 select 构建菜单,供用户选择 MySQL 版本
select mysql_version in 5.6 5.7 8.0
do
# 输出用户选择的 MySQL 版本
echo $mysql_version
done
27.用select实现选择水果,假设我们有如下水果可供选择:
Apple, Banana, Pear, Watermelons, Grape
#!/bin/bash
# 使用 select 构建菜单,供用户选择喜欢的水果
select fruit in Apple Banana Pear Watermelons Grape
do
# 输出用户选择的水果
echo "你最喜欢的水果是 $fruit"
# 跳出循环
break
done
28.打印九九乘法表
#!/bin/bash
# 外层循环,控制乘法表的行数
for i in {1..9}; do
# 内层循环,控制乘法表的列数
for j in {1..9}; do
# 仅当列数小于等于行数时,才进行乘法运算和输出
if [ $j -le $i ]; then
# 输出乘法表格,并计算乘积
echo -n "$i*$j = `expr $i \* $j` "
fi
done
# 输出换行,开始新的一行乘法表
echo ""
done
29.打印三角形
#!/bin/bash
# 外层循环,控制行数
for i in {1..9}; do
# 内层循环,输出每行前面的空格,用于形成倒三角形
for ((col=1; col<=10-i; col++)); do
echo -n " " # 输出空格
done
# 内层循环,输出每行的数字
for ((k=1; k<=i; k++)); do
echo -n "$i" # 输出当前行数
done
echo " " # 输出换行,开始新的一行
done
30. 使用case实现成绩优良差的判断
read -p "please input your score:" score
case $score in
[9][0-9]|100)
echo "优秀"
;;
[8][0-9])
echo "良好"
;;
[6][0-9]|[7][0-9])
echo "中等"
;;
*)
echo "不及格"
;;
esac
31.for ping测试指网段的主机
网段由用户输入,例如用户输入192.168.2 ,则ping 192.168.2.10 --- 192.168.2.20
UP: /tmp/host_up.txt
Down: /tmp/host_down.txt
#!/bin/bash
# 提示用户输入 IP 地址的最后一部分
read -p "请输入 IP 地址的最后一部分:" net
# 循环遍历给定范围内的 IP 地址
for i in {10..20}
do
# 拼接完整的 IP 地址
ip="$net.$i"
# ping IP 地址
ping -c 1 $ip > /dev/null
# 检查 ping 命令的返回值,0 表示成功,非 0 表示失败
if [ $? -eq 0 ]; then
# 追加记录到 host_up.txt 文件中
echo "$ip" >> /tmp/host_up.txt
else
# 追加记录到 host_down.txt 文件中
echo "$ip" >> /tmp/host_down.txt
fi
done
32.计算两个参数的和
#!/bin/bash
# 定义一个名为sum1的函数,用于计算两个数字的和
sum1() {
sum=$[$1 + $2] # 计算两个数字的和
echo $sum # 输出计算结果
}
# 从用户输入获取第一个数字
read -p "请输入第一个数字:" first
# 从用户输入获取第二个数字
read -p "请输入第二个数字:" second
# 调用sum1函数并传入用户输入的数字作为参数,但实际上传入的是字符串 "first" 和 "second",而不是变量的值
sum1 first second
# 或者
# 将sum1函数的输出保存到变量res中(这里的调用方式也是错误的,应该是将变量值传递给函数)
res=$(sum1 first second)
# 输出sum1函数的结果
echo $res
33.获取字符串的长度
#!/bin/bash
# 定义名为length的函数,用于计算字符串的长度
length() {
str=$1 # 将第一个参数赋值给变量str,即要计算长度的字符串
len=0 # 初始化长度为0
# 如果传入的字符串不为空,则计算其长度
if [ "$1" != "" ]; then
len=${#str} # 使用${#str}来获取字符串的长度
fi
# 将计算得到的长度作为返回值
return $len
}
# 调用length函数并传入字符串"abc123"作为参数,但是在脚本中并没有正确获取函数的返回值
length "abc123"
# 输出函数的返回值(但是这里的输出方法是错误的,应该使用$?来获取函数的返回值)
echo "字符串的长度为 $?"
34.将一个点分十进制格式的IP地址转换成点分二进制格式。
比如 255.255.255.255 --> 11111111.11111111.11111111.11111111
#!/bin/bash
# 定义一个名为ip_switch_bin的函数,用于将IP地址的每一部分转换为二进制表示
ip_switch_bin(){
ip=$1 # 将传入的第一个参数(IP地址)赋值给变量ip
# 使用awk将IP地址分割为四个数字,每个数字以点(.)为分隔符
ips=$(echo $ip | awk 'BEGIN{RS="."} print{}')
res="" # 初始化结果变量
# 遍历ips数组中的每个元素
for i in ${ips[@]}
do
# 将每部分的IP地址转换为二进制并追加到结果字符串res中
# 注意:这里的表达式应该是res+=$(echo "obase=2;$i" | bc),当前写法有语法错误
res+="obse=2;$i"|bc
done
echo $res # 输出最终的结果
}
# 调用ip_switch_bin函数,并将192.168.123.12作为参数传递
resbin=$(ip_switch_bin 192.168.123.12)
# 将结果按空格分割并用点(.)重新连接输出
echo $resbin | xargs echo | tr ' ' '.'
35.写一个脚本,判断给定的 IP 地址范围[192.168.72.130 ~ 192.168.72.140]是否在线。
#!/bin/bash
# 定义名为online的函数,用于检查指定IP范围内的主机是否在线
online() {
# 使用循环迭代指定的IP范围
for i in {148..152}
do
# 使用ping命令检查当前IP地址是否能够连通,并将输出重定向到/dev/null以隐藏输出信息
if ping -c1 192.168.72.$i &>/dev/null; then
# 如果ping命令成功,说明主机在线,打印提示信息
echo "192.168.72.$i is up"
else
# 如果ping命令失败,说明主机不在线,打印提示信息
echo "192.168.72.$i is unknown"
fi
done
}
# 调用online函数,开始检查主机在线状态
online
36.两数相加
#!/bin/bash
a=1 # 设置变量a的值为1
b=2 # 设置变量b的值为2
#c=$((a+b)) # 使用$(( ))语法计算a和b的和,并将结果赋值给变量c(已注释掉)
#let c=a+b # 使用let命令计算a和b的和,并将结果赋值给变量c(已注释掉)
#c=`expr $a + $b` # 使用expr命令计算a和b的和,并将结果赋值给变量c(已注释掉)
echo $c # 输出变量c的值(但是在脚本中未定义c,因此这里将输出空白)
37.根据用户输入的数值计算该数的阶乘
#!/bin/bash
# 定义递归函数,计算给定数值的阶乘
# 参数: $1 - 要计算阶乘的数值
# 返回值: 无
recursion() {
# 如果输入值为1,阶乘为1
if [ $1 -eq 1 ]; then
return 1
# 如果输入值大于1,使用递归计算阶乘
elif [ $1 -gt 1 ]; then
local n=$(($1-1))
recursion $n # 递归调用函数
let res=$1*$? # 计算阶乘结果
# 输入值无效
else
echo "error res"
fi
return $res # 返回阶乘结果
}
recursion 5 # 调用递归函数计算阶乘
echo $? # 打印阶乘结果
38.编写一个bash脚本以输出一个文本文件mywords.txt中第5行的内容。
假设 mywords.txt 内容如下:
welcome
to
nowcoder
this
is
shell
code
你的脚本应当输出:is
#!/bin/bash
# 使用sed命令从文件mywords.txt中提取第5行的内容,并将结果赋值给变量res
res=`cat mywords.txt | sed -n "5p"`
# 输出变量res的值
echo $res
39.使用函数递归/var/log目录,如果是文件直接输入文件名,如果是目录则输出目录名称并输出目录下所有子目录和文件名
#!/bin/bash
# 定义名为list_file的函数,用于递归遍历指定目录下的文件和子目录
list_file() {
for f in $(ls $1) # 循环遍历指定目录下的所有文件和目录
do
if [ -d "$1/$f" ]; then # 如果当前项是一个目录
echo "$2 directory $f" # 输出目录信息
list_file "$1/$f" "├── $2" # 递归调用list_file函数,遍历子目录
else
echo "$2 file $f" # 如果当前项是一个文件,则输出文件信息
fi
done
}
# 调用list_file函数,并传入第一个命令行参数作为要遍历的目录,同时传入一个空白的字符串作为初始的目录前缀
list_file $1 "├── "
40.数组遍历指定的目录
#!/bin/bash
# 接受一个目录作为参数,并将该目录下的所有文件存储在名为files的数组中
files=(`ls $1`)
# 循环遍历数组files中的所有元素
for((i=0;i<${#files[*]};i++)); do
echo ${files[$i]} # 输出数组中第i个元素(即文件名)
done
41.从标准输入读取 n 次字符串,每次输入的字符串保存在数组 array 中。
#!/bin/bash
# 设置循环次数
n=5
# 使用for循环遍历数组
for ((i=0; i<n; i++)); do
# 提示用户输入字符串
echo "Please input string... $((i + 1))"
# 读取用户输入并存储到数组中
read array[$i]
# 将数组中的元素赋值给变量b
b=${array[$i]}
# 打印出变量b的值
echo "$b"
done
42.将字符串中的字母逐个放入数组,并输出到标准输出
#!/bin/bash
# 定义字符串
str="hello"
# 获取字符串长度
len=${#str}
# 循环遍历字符串中的每个字符,并将其存入数组
for ((i=0; i<$len; i++))
do
# 从字符串中提取第 i 个字符并存储在变量 char 中
char="${str:i:1}"
# 将字符存入数组中
array[$i]=$char
# 输出数组中的每个元素到标准输出
echo ${array[$i]}
done
43.把1~3这3个数字存到数组中,分别乘以8后再依次输出
#!/bin/bash
# 将数字 1 到 3 存入数组
array=(`seq 3`)
# 循环遍历数组中的每个数字,并乘以 8 后依次输出
for ((i=0; i<${#array[*]}; i++))
do
# 计算乘以 8 后的结果
result=$((array[$i] * 8))
# 输出结果
echo $result
done
44.输出如下内容中字母数不大于6的单词。
cat is favorite to eat fish
#!/bin/bash
# 定义一个包含多个单词的数组
array=(cat is favorite to eat fish)
# 使用for循环遍历数组中的每个元素
for ((i=0;i<${#array[*]};i++))
do
# 使用expr命令获取当前元素的长度,并与6进行比较
if [ `expr length ${array[$i]}` -le 6 ]; then
echo ${array[$i]} # 如果长度小于等于6,输出当前元素
fi
done
45.写一个bash脚本以统计一个文本文件nowcoder.txt 中每个单词出现的个数。
为了简单起
见,你可以假设:wordcount.txt只包括小写字母和空格,每个单词只由小写字母组成,单词间由一个或
多个空格字符分隔。
假设 wordcount.txt 内容如下:
welcome nowcoder
welcome to nowcoder
nowcoder
你的脚本应当输出(以词频升序排列):
to 1
welcome 2
nowcoder 3
说明:不要担心个数相同的单词的排序问题,每个单词出现的个数都是唯一的。
cat wordcount.txt | # 从文件中读取内容并输出到标准输出(屏幕)
tr -s ' ' '\n' | # 将空格替换为换行符,实现将文本中的单词分隔开来
sort | # 对单词进行排序,以便后续uniq命令进行统计
uniq -c | # 统计重复的单词,并输出重复次数和单词本身
sort -r | # 对统计结果进行逆序排序,以便出现次数最多的单词在前面
awk '{print $2" "$1}' # 使用awk将单词和出现次数调换位置,并输出结果
46.监控cpu使用率的脚本
#利用while死循环+sleep实现
#!/bin/bash
# 无限循环,持续监测 CPU 使用率
while :
do
# 使用 top 命令获取 CPU 使用率,然后用 grep 过滤出包含 '%Cpu(s)' 的行,
# 再用 awk 提取出第 8 列(即 idle)的值,最后用 cut 命令按 '.' 分割并取第一个字段,
# 这样我们得到了 CPU 空闲百分比的整数部分
idle=$(top -bn1 | grep '%Cpu(s)' | awk '{print $8}' | cut -d. -f1)
# 计算 CPU 使用率,假设 CPU 使用率等于 100 减去 CPU 空闲百分比
use=$((100 - idle))
# 如果 CPU 使用率大于 5%,则打印警告信息
if [ $use -gt 5 ]; then
echo "CPU use too high"
fi
# 等待 10 秒钟后再次检查 CPU 使用率
sleep 10
done