特殊变量
$0
:代表当前执行文件的文件名称, 如果是带路径执行的会把路径也返回出来$#
:代表当前脚本执行时增加的参数个数, 是个数字;$$
:代表当前脚本执行时所分配的pid号;$@
:代表传递给脚本或者函数的所有参数;$n
:代表位置参数,1 <= n <= 正无穷
;
比较运算符
-eq
:等于;
-ne
:不等于;-gt
:大于;-lt
:小于;-ge
:大于等于;-le
:小于等于;[ -f FILENAME ]
用来判断单个文件是否存在;[ -d DIRNAME ]
用来判断目录是否存在;
变量
定义变量
定义变量时,变量名不加美元符号($),如:
your_name="zhoupeng"
注意这里和其他编程语言不同的是,变量名和等号之间不能有空格
除了显式地直接赋值,还可以用语句给变量赋值,如:
# 遍历`/etc`目录中的所有文件和子目录,并将它们的名称一个一个赋值给变量`file`并且打印
for file in `ls /etc`; do
echo $file
done
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="zhoupeng"
echo $your_name
echo ${your_name} # 标准写法,推荐养成习惯
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,比如下面这种情况:
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
如果不给skill变量加花括号,写成echo "I am good at $skillScript",解释器就会把$
skillScript当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。
重定义变量
已定义的变量,可以被重新定义,如:
your_name="zhoupeng"
echo $your_name
your_name="shuaipeng"
echo $your_name
字符串
字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号(强引)
str='this is a string'
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 单引号字串中不能出现单引号(对单引号使用转义符后也不行)
双引号(弱引)
your_name='zhoupeng'
str="Hello, I know your are \"$your_name\"! \n"
- 双引号里可以有变量
- 双引号里可以出现转义字符
字符串操作
拼接字符串
your_name="zhoupeng"
str="hello, "$your_name" !"
str_1="hello, ${your_name} !"
echo $str $str_1
获取字符串长度
str="abcd"
echo ${#str} #输出:4
提取子字符串
str="May you be brave and happy"
echo ${str:4:3} #输出:you
查找子字符串
str="May you be brave and happy"
echo `expr index "$str" b`
# 输出:9
# 这个语句的意思是:找出字母b在这名话中的位置,要在linux下运行,mac下会报错
条件判断
sh里的if [ $foo -eq 0 ],这个方括号跟别的编程语言后面的圆括号大不相同,它是一个可执行程序(和ls, grep一样)
[root@tx ~]# ls -l /usr/bin/[
-rwxr-xr-x 1 root root 41488 Nov 17 2020 /usr/bin/[
正因为方括号在这里是一个可执行程序,方括号后面必须加空格,不能写成if [$foo -eq 0]
if
number=5
# 使用if语句检查数字是否大于零
if [ $number -gt 0 ]; then
echo "数字大于零"
fi
c语言形式
if ((2>1));then
echo 'yes'
elif((1>2));then
echo 'no'
else
echo 'exit'
fi
写成一行:
number=5; if [ ${number} -gt 0 ]; then echo "数字大于零" ; fi
if else
number=3
# 使用if语句检查数字是否大于5
if [ $number -gt 5 ]; then
echo "数字大于5"
else
echo "数字小于5"
fi
写成一行:
number=3; if [ ${number} -gt 5 ]; then echo "数字大于5" ; else echo "数字小于5"; fi
if else-if else
number=5
# 使用if-elif-else语句检查数字的大小
if [ $number -gt 5 ]; then
echo "数字大于5"
elif [ $number -eq 5 ]; then
echo "数字等于5"
else
echo "数字小于5"
fi
写成一行:
number=5; if [ $number -gt 5 ]; then echo "数字大于5"; elif [ $number -eq 5 ]; then echo "数字等于5"; else echo "数字小于5"; fi
流程控制
for
# 遍历`/etc`目录中的所有文件和子目录,并将它们的名称一个一个赋值给变量`file`并且打印
for file in `ls /etc`; do
echo $file
done
写成一行:
for file in `ls /etc`; do echo ${file}; done
C语言风格的for
# 使用C语言风格的for循环打印数字
for ((i = 0; i < 5; i++)); do
echo "循环迭代 $i"
done
while
#!/bin/bash
count=1
# 使用 while 循环打印数字,直到 count 变量的值大于等于 5
while [ $count -le 5 ]; do
echo "循环迭代 $count"
((count++)) # 递增计数器
done
无限循环
while :
do
echo 123
done
或者
while true
do
echo 123
done
或者
for (( ; ; ));do
echo 123
done
case
#!/bin/bash
echo "请输入一个数字 (1-4):"
read num # 读取用户输入的数字赋值给num
# 使用 case 语句根据用户输入执行不同的操作
case $num in
1)
echo "你选择了数字 1"
;;
2)
echo "你选择了数字 2"
;;
3)
echo "你选择了数字 3"
;;
4)
echo "你选择了数字 4"
;;
*)
echo "无效的输入,输入应为 1-4 之间的数字"
;;
esac
当编写Shell脚本时,与用户输入有关的内容通常涉及到如何获取、处理和利用用户提供的信息。下面我将为你撰写有关Shell脚本中用户输入的内容:
用户输入
在Shell脚本中,与用户输入有关的操作是非常常见的,因为它们允许脚本与用户进行交互。有多种方式可以实现用户输入:
执行脚本时传入
执行脚本时传入参数是一种非常有用的方式,可以在脚本中使用这些参数。这对于根据不同的输入执行不同的操作非常有用。例如:
# 脚本名为myscript.sh
# 执行: ./myscript.sh 文件1.txt 文件2.txt
file1=$1
file2=$2
echo "比较文件 $file1 和 $file2"
diff $file1 $file2
在这个示例中,脚本通过命令行参数传入两个文件名,然后使用diff
命令比较这两个文件。
脚本运行中输入
有时,你可能需要在脚本运行期间与用户交互,而不是在脚本开始时就获取所有输入。这可以通过使用read
命令来实现。例如:
#!/bin/bash
echo "请输入一个数字:"
read num
# read -p "输出字符串" num
if [ $num -eq 0 ]; then
echo "您输入了零。"
else
echo "您输入的数字不是零。"
fi
select菜单
select
是一个用于创建选择菜单的特殊命令。它允许用户从列表中选择一个选项,然后执行相应的操作。例如:
#!/bin/bash
PS3="请选择一个颜色: " # `PS3` 则用于 `select` 命令的菜单提示。
options=("红色" "绿色" "蓝色" "退出")
select color in "${options[@]}"; do
case $color in
"红色")
echo "你选择了红色。"
;;
"绿色")
echo "你选择了绿色。"
;;
"蓝色")
echo "你选择了蓝色。"
;;
"退出")
break
;;
*)
echo "无效的选项。"
;;
esac
done
函数
在Shell脚本中,函数是一种将一系列命令组织在一起并赋予其名称的方法。使用函数可以使脚本更具模块化和可读性,同时可以避免代码的重复编写。函数在需要时可以被多次调用,使得代码更加灵活和易于维护。
#!/bin/bash
# 定义一个名为 demo 的函数
demo() {
echo "Hello, $1!" # $1 表示第一个参数
}
# 调用函数 demo,传递参数 "Alice"
demo "world"
数组
在Shell脚本中,数组是一种用于存储多个值的数据结构。数组允许你按顺序存储多个元素,并使用索引来访问这些元素。
声明数组
fruits=("apple" "banana" "cherry" "date")
访问数组元素
echo ${fruits[0]} # 输出第一个元素 "apple"
数组的长度
length=${#fruits[@]}
echo "数组 array 的长度为 $length"
遍历数组
fruits=("apple" "banana" "cherry" "date")
# 遍历数组并输出每个元素
for fruit in "${fruits[@]}"; do
echo "水果:$fruit"
done
添加和删除数组元素
fruits=("apple" "banana" "cherry")
fruits+=("date") # 向数组添加一个新元素
unset fruits[1] # 删除数组中的第二个元素(索引为1)
关联数组
Shell中还支持关联数组,其中每个元素都有一个关联的键。关联数组使用不同的语法来声明和访问元素。
# 声明关联数组
declare -A colors
colors["red"]="红色"
colors["green"]="绿色"
colors["blue"]="蓝色"
# 访问关联数组元素
echo "红色对应的颜色是 ${colors["red"]}"
Shell练习
2. 通过变量创建 Linux 系统账户及密码
#!/bin/bash
echo "input the userid:"
read user_id
echo "input the $user_id password:"
read user_password
useradd $user_id
echo "$user_id:$user_password" | chpasswd
echo "Complete creation!"
3. 每周 5 使用 tar 命令备份/var/log 下的所有日志文件
#vim /root/logbak.sh
#编写备份脚本,备份后的文件名包含日期标签,防止后面的备份将前面的备份数据覆盖
#注意 date 命令需要使用反引号括起来,反引号在键盘<tab>键上面
tar -czf log-`date +%Y%m%d`.tar.gz /var/log
# crontab ‐e #编写计划任务,执行备份脚本
00 03 * * 5 /root/logbak.sh
5. 实时监控本机内存和硬盘剩余空间,发送报警邮件给管理员
#!/bin/bash
while :
do
#获取磁盘内存剩余空间
mem_size=$(free -m | awk '/Mem/{print $4}')
disk_size=$(df -m / |awk '/\\//{print $4}')
#判断磁盘剩余空间
if [ $disk_size -le 4096 ] ;then
curl "<https://api.day.app/oV7gwE66V9CVfawx7oRGyD/'/'分区磁盘空间不足,当前/目录剩余$disk_size>" 1>>/dev/null 2>>/dev/null
fi
#判断内存剩余空间
if [ $mem_size -le 2048 ];then
curl "<https://api.day.app/oV7gwE66V9CVfawx7oRGyD/内存资源不足,剩余内存$mem_size>" 1>>/dev/null 2>>/dev/null
fi
sleep 60
done
6. 脚本生成一个 100 以内的随机数,提示用户猜数字,根据用户的输入,提示用户猜对了,
猜小了或猜大了,直至用户猜对脚本结束。
#!/bin/bash
#RANDOM 为系统自带的系统变量,值为 0‐32767 的随机数
#使用取余算法将随机数变为 1‐100 的随机数
num=$[RANDOM%100+1]
#使用 read 提示用户猜数字
#使用 if 判断用户猜数字的大小关系:‐eq(等于),‐ne(不等于),‐gt(大于),‐ge(大于等于),‐lt(小于),‐le(小
于等于)
while :
do
read ‐p "计算机生成了一个 1‐100 的随机数,你猜: " cai
if [ $cai ‐eq $num ];then
echo "恭喜,猜对了"
exit
elif [ $cai ‐gt $num ];then
echo "Oops,猜大了"
else
echo "Oops,猜小了"
fi
7. 检测本机当前用户是否为超级管理员,如果是管理员,则使用 yum 安装 vsftpd,如果不
是,则提示您非管理员(使用字串对比版本)
#!/bin/bash
if [ $USER == "root" ];then
yum ‐y install vsftpd
else
echo "您不是管理员,没有权限安装软件"
fi
8. 检测本机当前用户是否为超级管理员,如果是管理员,则使用 yum 安装 vsftpd,如果不
是,则提示您非管理员(使用 UID 数字对比版本)
#!/bin/bash
if [ $UID ‐eq 0 ];then
yum ‐y install vsftpd
else
echo "您不是管理员,没有权限安装软件"
fi
9. 编写脚本:提示用户输入用户名和密码,脚本自动创建相应的账户及配置密码。如果用户
不输入账户名,则提示必须输入账户名并退出脚本;如果用户不输入密码,则统一使用默
认的 123456 作为默认密码。
#!/bin/bash
read ‐p "请输入用户名: " user
#使用‐z 可以判断一个变量是否为空,如果为空,提示用户必须输入账户名,并退出脚本,退出码为 2 #没有输入用户名脚本退出后,使用$?查看的返回码为 2
if [ ‐z $user ];then
echo "您不需输入账户名"
exit 2
fi
#使用 stty ‐echo 关闭 shell 的回显功能
#使用 stty echo 打开 shell 的回显功能
stty ‐echo
read ‐p "请输入密码: " pass
stty echo
pass=${pass:‐123456}
useradd "$user"
echo "$pass" | passwd ‐‐stdin "$user"
10. 依次提示用户输入 3 个整数,脚本根据数字大小依次排序输出 3 个数字
#!/bin/bash
read ‐p "请输入一个整数:" num1
read ‐p "请输入一个整数:" num2
read ‐p "请输入一个整数:" num3
#不管谁大谁小,最后都打印 echo "$num1,$num2,$num3"
#num1 中永远存最小的值,num2 中永远存中间值,num3 永远存最大值
#如果输入的不是这样的顺序,则改变数的存储顺序,如:可以将 num1 和 num2 的值对调
tmp=0
#如果 num1 大于 num2,就把 num1 和和 num2 的值对调,确保 num1 变量中存的是最小值
if [ $num1 ‐gt $num2 ];then
tmp=$num1
num1=$num2
num2=$tmp
fi
#如果 num1 大于 num3,就把 num1 和 num3 对调,确保 num1 变量中存的是最小值
if [ $num1 ‐gt $num3 ];then
tmp=$num1
num1=$num3
num3=$tmp
fi
#如果 num2 大于 num3,就把 num2 和 num3 对标,确保 num2 变量中存的是小一点的值
if [ $num2 ‐gt $num3 ];then
tmp=$num2
num2=$num3
num3=$tmp
fi
echo "排序后数据为:$num1,$num2,$num3"
11. 编写脚本,实现人机<石头,剪刀,布>游戏
#!/bin/bash
game=(石头 剪刀 布)
num=$[RANDOM%3]
computer=${game[$num]}
#通过随机数获取计算机的出拳
#出拳的可能性保存在一个数组中,game[0],game[1],game[2]分别是 3 中不同的可能
echo "请根据下列提示选择您的出拳手势"
echo "1.石头"
echo "2.剪刀"
echo "3.布"
read ‐p "请选择 1‐3:" person
case $person in
1)
if [ $num ‐eq 0 ];then
echo "平局"
elif [ $num ‐eq 1 ];then
echo "你赢"
else
echo "计算机赢"
fi;;
2)
if [ $num ‐eq 0 ];then
echo "计算机赢"
elif [ $num ‐eq 1 ];then
echo "平局"
else
echo "你赢"
fi;;
3)
if [ $num ‐eq 0 ];then
echo "你赢"
elif [ $num ‐eq 1 ];then
echo "计算机赢"
else
echo "平局"
fi;;
*)
echo "必须输入 1‐3 的数字"
esac
12. 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机
状态(for 版本)
#!/bin/bash
for i in {1..254}
do
ping ‐c2 ‐i0.3 ‐W1 192.168.4.$i &>/dev/null
if [ $? –eq 0 ];then
echo "192.168.4.$i is up"
else
echo "192.168.4.$i is down"
fi
done
13. 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机
状态(while 版本)
#!/bin/bash
i=1
while [ $i ‐le 254 ]
do
ping ‐c2 ‐i0.3 ‐W1 192.168.4.$i &>/dev/null
if [ $? –eq 0 ];then
echo "192.168.4.$i is up"
else
echo "192.168.4.$i is down"
fi
let i++
done
14. 编写脚本测试 192.168.4.0/24 整个网段中哪些主机处于开机状态,哪些主机处于关机
状态(多进程版)
#!/bin/bash
#定义一个函数,ping 某一台主机,并检测主机的存活状态
myping(){
ping ‐c2 ‐i0.3 ‐W1 $1 &>/dev/null
if [ $? ‐eq 0 ];then
echo "$1 is up"
else
echo "$1 is down"
fi
}
for i in {1..254}
do
myping 192.168.4.$i &
done
#使用&符号,将执行的函数放入后台执行
#这样做的好处是不需要等待 ping 第一台主机的回应,就可以继续并发 ping 第二台主机,依次类推。
15. 编写脚本,显示进度条
#!/bin/bash
jindu(){
while :
do
echo ‐n '#'
sleep 0.2
done
}
jindu &
cp ‐a $1 $2
killall $!
echo "拷贝完成''
标签:脚本,bin,else,test,fi,echo,输入
From: https://www.cnblogs.com/ppmdz/p/17983058