echo -n 表示不换行输出
echo -e 表示输出转义符
常用的转义符有:
选项 | 作用 |
---|---|
\r | 光标移至行首,并且不换行 |
\s | 当前shell的名称,如bash |
\t | 插入Tab键,制表符 |
\n | 输出换行 |
\f | 换行,但光标仍停留在原处 |
\ | 表示插入"\"本身转义 |
\b | 表示退格 不显示前一个字符 |
\c | 抑制更多的输出或不换行 |
关于 \b 用法
[root@localhost ~]#echo -e "12345\b678"
##退格删除前面的字符
1234678
[root@localhost ~]#echo -e "12345\b\b678"
123678
[root@localhost ~]#echo -e "12345\b\b\b678"
12678
[root@localhost ~]#echo -e "12345\b\b\b\b678"
16785
###注意退格键和末尾的字符相关,超过末尾的字符数量 会出bug
关于换行
[root@localhost ~]#echo "123456"
123456
#正常换行输出
[root@localhost ~]#echo -n "123456"
123456[root@localhost ~]#
#不换行输出
[root@localhost ~]#echo -e "123456\c"
123456[root@localhost ~]#
[root@localhost ~]#echo -e "123456\c789"
123456[root@localhost ~]#
###\c 注意 使用在数字中间会把后面内容删除
使用 \n 可以实现输出换行(回车)的操作。
比如实现自动硬盘分区
#!/bin/bash
read -p "请输入你要分区的设备(/dev/sd*):" disk
read -p "请输入你要分区的大小(+数字G):" num
echo -e "n\n\n\n\n${num}\nw\n " | fdisk ${disk}
[root@localhost data]#date #查看当前系统时间
2024年 01月 25日 星期四 22:33:46 CST
[root@localhost data]#date +%F #完整格式显示日期
2024-01-25
[root@localhost data]#date +%T #完整格式显示时间
22:40:39
[root@localhost data]#date +%F-%T #时间与日期使用 - 号分隔
2024-01-25-22:42:37
[root@localhost data]#date '+%F '%T #时间与日期使用 空格 号分隔
2024-01-25 22:42:48
[root@localhost data]#date -d "-3 day" #前三天
2024年 01月 22日 星期一 22:45:40 CST
[root@localhost data]#date -d "+3 day" #后三天
2024年 01月 28日 星期日 22:45:46 CST
[root@localhost data]#date -d '-3 day' '+%F '%T
2024-01-22 22:46:20
日历:
[root@localhost data]#cal 2024
#查看日历
[root@localhost data]#cal 9 2024 #查看哪一年哪一月的日历。
九月 2024
日 一 二 三 四 五 六
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
关于 计划任务 crontab 里 不能有 % 号,想要使用 要加 \ 转义符
30 2 * * * /bin/cp -a /etc/ /data/etc`date +\%F_\%T`
!!!!!!!!!不加转义符号无法识别!!!!!!!!!!!
30 2 * * * /bin/cp -a /etc/ /data/etc`date +‘%F_%T’` #无法执行。
3. seq
[root@localhost data]#seq 3
1
2
3
[root@localhost data]#seq 1 2 10
#从1 开始 步长为2 到10 为止
1
3
5
7
9
[root@localhost data]#seq 0 2 10
#从 0 开始 步长为 2 到10 为止 都为偶数。
0
2
4
6
8
10
[root@localhost data]#seq 3 -1 1
#从 3 开始 依次 减 1 ,到 1 为止。
3
2
1
[root@localhost data]#seq 3 -1 -1
3
2
1
0
-1
循环含义
将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数
常见的循环的命令:for, while, until
语法:
for 变量名 in {list}
do
command(需要循环的事件)
done
for i in {1..10}
do
echo "i=$i"
done
1.for循环有次数
2.for循环开始时,会对变量i进行赋值
3.for循环在赋值后,会执行do 和done之间的代码
4.for循环在第一次循环后执行到done,再次赋值第二个
5.for循环在赋值后,会执行do 和done之间的代码
6.for循环在第一次循环后执行到done,再次赋值第三个
7.for循环在赋值后,会执行do 和done之间的代码
花括号的用法
花括号{}和seq在for循环的应用:
for i in {1..50..2} 1-50的奇数
do
echo "$i"
done
for i in {2..50..2} 2-50的偶数
for i in {10..1} 1-10倒序排列
$() 和 `` 都是调用命令的执行结果。
for i in $(seq 10) 1-10正序排列
for i in $(seq 10 -1 1) 1-10倒序排列
for i in $(seq 1 2 10) 1-10的奇数,中间为步长
#要想有结果要在后面输入完整的格式。
语法:
for 变量名
do
command
done
例子:
1. 打印 hello
[root@server ~]# vim for2.sh
#!/bin/bash
for i
do
echo hello
done
[root@server ~]#bash for2.sh
#没有给脚本传参所以执行了没有结果
[root@server ~]#bash for2.sh a
#把a赋值给变量i,i有值了它就开始执行do..done了
hello
语法:
for (( 表达式1; 表达式2; 表达式3 )); do 命令; done
for ((expr1;expr2;expr3))
do
command
done
expr1:定义变量并赋初值
expr2:决定是否循环
expr3:决定循环变量如何改变,决定循环什么时候退出
比如:
sum=0
for ((i=0;i<=100;i++))
do
sum=$[sum+i]
done
echo "$sum"
计算 1 到 100 累加的值 5050
i=0 是给 i 变量赋值为 0
i<=100 是定义 变量的范围 在范围内继续循环,不在结束循环。
i++ 是 变量 i 每运行一次都会加1。
let sum+=i 等于 let sum=sum+i
#需要使用 let 命令
++ 自身变量+1
-- 自身变量-1
+=5 自身变量+5
-=5 自身变量-5
*=5 自身变量*5
/=5 自身变量/5
%=5 自身变量%5
使用脚本 输出 十次 hello world 。
#!/bin/bash
for i in {1..10}
do
echo "hello world"
done
不编辑脚本 使用命令 输出 十次 hello world 。
[root@localhost data]#for i in {1..10};do echo "hello world";done
或
[root@localhost data]#for i in `seq 10`;do echo "hello world";done
使用三种方法过滤出当前目录下 以 sh 结尾的文件 且 只显示文件名。
[root@localhost data]#ls|grep sh$
[root@localhost data]#find -name '*sh'|cut -d "/" -f2
[root@localhost data]#for i in *sh;do echo $i;done
#当前目录下以sh 结尾的文件名 会赋值给 变量 i ,然后输出变量,然后循环 直至 全部输出 停止循环。
[root@localhost data]#vim he.sh
#!/bin/bash
sum=0
for i in {1..100..2}
do
sum=$[sum+i]
done
echo "1到100的奇数和为:$sum"
sum=0
for i in {0..100..2}
do
sum=$[sum+i]
done
echo "1到100的偶数和为:$sum"
[root@localhost data]#bash he.sh
1到100的奇数和为:2500
1到100的偶数和为:2550
另一种格式:
#!/bin/bash
sum=0
for ((i=0;i<=100;i+=2))
do
sum=$[sum+i]
done
echo "$sum"
sum=0
for ((i=1;i<=100;i+=2))
do
sum=$[sum+i]
done
echo "$sum"
正 九九乘法表
#!/bin/bash
for j in {1..9}
do
for i in `seq $j`
do
echo -e "${i}x${j}=$[i*j]\t\c"
#\t 可以对齐
#\c 不换行(要放在最后)
done
echo
done
倒 九九乘法表
#!/bin/bash
for j in {9..-1..1}
do
for i in `seq $j`
do
echo -e "${i}x${j}=$[i*j]\t\c"
done
echo
done
#!/bin/bash
read -p "请输入你要添加的用户名称:" usr
for uname in $usr
do
useradd $uname
echo "123123" |passwd --stdin $uname &>/dev/null
done
或
#!/bin/bash
ulist=$(cat /opt/user.txt) #用户名称文件
for uname in $ulist
do
useradd $uname
echo "123123" |passwd --stdin $uname &>/dev/null
done
[root@localhost ~]#cat /opt/user.txt
lisi
wangwu
zhangsan
#!/bin/bash
ip=192.168.80.
for i in {1..254}
do
{
ping -c2 -W2 ${ip}${i} &> /dev/null
if [ $? -eq 0 ];then
echo "$i is up" >> /mnt/up.txt
#正确结果追加到/mnt/up.txt 文件里
else
echo "$i is down" >> /mnt/down.txt
#错误结果追加到/mnt/down.txt 文件里
fi
} &
done
#!/bin/bash
read -p "你想要在mnt目录下改什么后缀的文件(输入后缀):" w
b=`find /mnt/* -name "*.${w}" | wc -l`
if [ $b -gt 0 ];then
read -p "你想要改后缀为:" h
file=`ls /mnt/*.${w}|cut -d "/" -f3`
for i in $file
do
name=`echo $i | cut -d "." -f1`
mv /mnt/$i /mnt/${name}.${h}
done
else
echo -e "\E[1;35m没有这个后缀的文件\E[0m"
echo
bash $0
fi
纯属乱加的,^-^
批量改后缀名:
DIR=/data/test
cd $DIR || { echo 无法进入 $DIR;exit 1; }
for FILE in *
do
PRE=`echo $FILE|grep -Eo ".*\."`
mv $FILE ${PRE}bak
done
#!/bin/bash
cd /data
for file in *
do
name=`echo $file |cut -d "." -f1`
mv $file ${name}.bak
done
$RANDOM 取值范围: 0-32767
[root@test1 ~]# echo $[$RANDOM%50]
37
#随机输出 0-49 以内的随机数。
[root@test1 ~]# echo $[$RANDOM%50+1]
1
#随机输出 1-50 以内的随机数。
相对于for,需要知道循环次数
我们只知道停止条件,不知道次数,就需要使用 while
直到达到条件
while循环
1、语法结构
2、死循环
while循环一般用于有条件判断的循环,若判断条件为真,则进入循环,当条件为假就跳出循环
格式:
while 条件判断
do
命令
done
当命令判断为假时停止
死循环:
while死循环
while [ 1 -eq 1 ] //写一个永远为真的表达式,1等于1这个条件永远为真,所以这个脚本会一直循环下去
do
command
done
#因为1 永远等于 1 ,所以会一直循环。
while true
do
command
done
while :
do
command
done
: 是一个空的命令。没有效果; 此命令不做任何操作。 表示总是成功(总为真)
#!/bin/bash
i=1
while [ "${i}" -le 33 ]
#循环33次 ,变量小于等于33
do
useradd stu${i}
#建立stu1 至 stu33 的用户
echo "123456" |passwd --stdin stu${i} &>/dev/null
if [ $? -eq 0 ]
#使用 $? 判断上一次命令执行结果是否为0(真)
then
echo "用户 stu${i} 被建立"
#等于 0 执行上面语句,不等于执行下面语句
else
echo "用户 stu${i} 建立失败"
fi
let i++
#每循环一次都要给变量加1。
done
while 格式
#!/bin/bash
p=`echo $[RANDOM%2000+1]`
t=0
while true
do
read -p "请输入商品的价格1-1000:" num
let t++
if [ $num -eq $p ]
then
echo "恭喜你猜中了,实际价格是$p"
echo "您一共猜了${t}次"
exit 0
#退出循环,不加会一直循环。
elif [ $num -gt $p ]
then
echo "您猜的价格高了"
else
echo "您猜的价格低了"
fi
done
break跳出单个循环 break n 数字数字是几代表跳出n层循环
continue终止某次循环中的命令,但是不会完全终止命令
exit 直接退出脚本
关于 continue
[root@localhost ~]#cat continue.sh
#结束某次循环
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 5 ]
then continue
fi
echo i=$i
done
#then后面加上continue 的意思是当变量等于 5 时终止当前循环,但第 6 次循环还会继续执行。
关于 break
[root@localhost ~]#cat break.sh
#结束一层循环
#!/bin/bash
for j in {1..9} #行数
do
for i in {1..9} #列数
do
if [ $i -eq 5 ]
then
break
fi
echo -n "i=$i "
done
echo
done
#结果 等于 5 时直接结束 本层 循环。 for j in {1..9} 还会继续执行。
[root@localhost dst]#bash break.sh
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
i=1 i=2 i=3 i=4
#可以看到 到第四列的时候就没有了 ,这是因为 负责列数的循环已经停止执行了,但行数的
循环还在执行,所以就会出现 九行 四列的情况。
关于 exit
[root@localhost ~]#cat break.sh
#结束一层循环
#!/bin/bash
for j in {1..9} #行数
do
for i in {1..9} #列数
do
if [ $i -eq 5 ]
then
exit
fi
echo -n "i=$i "
done
echo
done
#这个将更加暴力,执行第一次行数循环 后 列数的循环执行到第五次将直接退出脚本,不再执行任何的循环。
[root@localhost dst]#bash break.sh
i=1 i=2 i=3 i=4 [root@localhost dst]#
until 循环与 while 循环类似,while 循环能实现的脚本 until 同样也可以实现,但区别是while 循环在条件为真是继续执行循环,而 until 则是在条件为假时执行循环
until 循环语句的语法结构如下所示。
until 条件测试操作
do
命令序列
done
实例1:求和
#!/bin/bash
sum=0
i=0
until [ $i -gt 100 ]
#变量 i 为假 (不大于 100),将执行循环,当变量大于100退出循环。
do
let sum=$i+$sum
let i++
done
echo sum=$sum
实例2:判断用户是否在线,在线就发消息。
#!/bin/bash
username=$1
if [ $# -lt 1 ]
then
echo "请在脚本后输入 用户名和发送信息"
exit 1
fi
if grep "^$username" /etc/passwd &>/dev/null
then :
else
echo "用户不存在"
exit 1
fi
until who |grep $username &>/dev/null
do
echo "用户不在线"
sleep 5
done
mes=$2
echo $mes |write $username
[root@localhost data]#help select
select: select NAME [in 词语 ... ;] do 命令; done
从列表中选取词并且执行命令。
WORDS 变量被展开,生成一个词的列表。展开的词集合被打印
在标准错误输出设备上,每个以一个数字做前缀。如果没有 `in WORDS'
则假定使用`in "$@"'。PS3提示符会被显示并且从标准输入读入一行
如果该行由被显示的词对应的数字组成,则 NAME 变量被设定为相应
的词。如果行为空,则 WORDS 变量和提示符被重新显示。如果读取了
文件结束符,则命令完成。读入任何其他的值会导致 NAME 变量被设定
为空。读入的行被存放在变量 REPLY 中。COMMANDS 命令在每次选择
之后执行直到执行一个 break 命令。
退出状态:
返回最后一个执行的命令的状态。
一定要使用$REPLY
[root@localhost ~]#select menu in 配置网卡 配置yum源;do echo $menu;done
1) 配置网卡
2) 配置yum源
#? 1
配置网卡
#? 2
配置yum源
#?
[root@localhost ~]#PS3="请选择功能(1-2):";select menu in 配置网卡 配置yum源;do echo $menu;done
1) 配置网卡
2) 配置yum源
请选择功能(1-2):1
配置网卡
请选择功能(1-2):2
配置yum源
请选择功能(1-2):
PS1 提示符
PS2 多行重定向
PS3 菜单选择
例子:
#!/bin/bash
sum=0
PS3="请输入(1-6):"
MENU="
宫保鸡丁
酸菜鱼
鱼香肉丝
佛跳墙
水煮肉片
点菜结束
"
select menu in $MENU
do
case $REPLY in
1)
echo $menu 价格是20
let sum+=20
;;
2)
echo $menu 价格是60
let sum+=60
;;
3)
echo $menu 价格是25
let sum+=25
;;
4)
echo $menu 价格是150
let sum+=150
;;
5)
echo $menu 价格是60
let sum+=60
;;
6)
echo "点菜结束"
break
;;
*)
echo "点菜错误,请重新选择"
;;
esac
done
echo "总价是$sum"
#!/bin/bash
cat <