- shell
执行shell脚本的方式
方式一:bash
bash test.sh
方式二:./
./test.sh
方式三: 使用脚本完整路径
/root/test.sh
方式四:使用source,以当前默认 Shell 解释器执行
source test.sh
常用系统变量
在命令行提示符直接执行 env、set 查看系统或环境变量。
系统变量 作用
$HOME 当前用户家目录
$SHELL 默认 Shell
$IFS 内部字段分隔符
$LANG 默认语言
$PATH 默认可执行程序路径
$PWD 当前目录
$UID 当前用户 ID
$USER 当前用户
$HISTSIZE 历史命令大小,可通过 HISTTIMEFORMAT 变量设置命令执行时间
$RANDOM 随机生成一个 0 至 32767 的整数
$BASHPID 当前bash的PID号
$HOSTNAME 主机名
ps axjf 输出的第一列是 PPID(父进程 ID),第二列是 PID(子进程 ID)
位置变量
位置变量指的是函数或脚本后跟的第 n 个参数。
$1-n,需要注意的是从第 10 个开始要用花括号调用,例如${10}
shift 可对位置变量控制,例如:
#!/bin/bash
echo "1: $1"
shift
echo "2: $2"
shift
echo "3: $3"
# bash test.sh a b c
1: a
2: b
3: c
每执行一次 shift 命令,位置变量个数就会减一,而变量值则提前一位。shift n,可设置向前移动n位。
特殊变量
变量名 作用
$0 脚本自身名字
$1 脚本后跟的第一个位置参数,如果个数超过10,需要使用{}
$* 显示脚本后跟的所有参数,所有的位置参数被看做一个字符串
$@ 显示脚本后跟的所有参数,每个位置参数被看做独立的字符串
$# 显示参数的个数
$? 显示上条命令的执行结果,0为成功,非0失败,范围0-255
$$ 当前进程 PID
$! 上一条运行后台进程的 PID
变量引用
赋值运算符 示例
= 变量赋值
+= 两个变量相加
自定义变量与引用
[root@zhongxiaofei ~]# VAR=123
[root@zhongxiaofei ~]# echo $VAR
123
[root@zhongxiaofei ~]# VAR+=666
[root@zhongxiaofei ~]# echo $VAR
123666
Shell 中所有变量引用使用$符,后跟变量名。
有时个别特殊字符会影响正常引用,那么需要使用${VAR},例如:
[root@zhongxiaofei ~]# VAR=123
[root@zhongxiaofei ~]# echo $VAR
123
[root@zhongxiaofei ~]# echo $VAR_
[root@zhongxiaofei ~]# echo ${VAR}
123
还有时候变量名与其他字符串紧碍着,也会误认为是整个变量:
[root@zhongxiaofei ~]# echo $VAR666
[root@zhongxiaofei ~]# echo ${VAR}666
123666
将命令结果作为变量值
[root@zhongxiaofei ~]# VAR=`date`
[root@zhongxiaofei ~]# echo $VAR
Mon Oct 25 18:05:14 CST 2021
[root@zhongxiaofei ~]#
[root@zhongxiaofei ~]# VAR=$(date)
[root@zhongxiaofei ~]# echo $VAR
Mon Oct 25 18:05:27 CST 2021
这里的反撇号等效于$(),都是用于执行 Shell 命令。
双引号和单引号
在变量赋值时,如果值有空格,Shell 会把空格后面的字符串解释为命令:
[root@zhongxiaofei ~]# VAR=2 3 4
bash: 3: command not found
[root@zhongxiaofei ~]# VAR="2 3 4"
[root@zhongxiaofei ~]# echo $VAR
2 3 4
[root@zhongxiaofei ~]# VAR='3 3 4'
[root@zhongxiaofei ~]# echo $VAR
3 3 4
看不出什么区别,再举个说明:
[root@zhongxiaofei ~]# N=2
[root@zhongxiaofei ~]# VAR="1 $N"
[root@zhongxiaofei ~]# echo $VAR
1 2
[root@zhongxiaofei ~]# VAR='1 $N'
[root@zhongxiaofei ~]# echo $VAR
1 $N
单引号是告诉 Shell 忽略特殊字符,而双引号则解释特殊符号原有的意义,比如$、!。
单引号:所见即所得
反引号:先执行里面的命令
双引号:会对具有特殊意义的字符做解析
shell注释
Shell 注释也很简单,只要在每行前面加个#号,即表示 Shell 忽略解释。
变量赋值总结
变量赋值语句
向变量中写入内容。vimvv
#read
-p 交互的时候提示信息。
-t 超过这个时间没有操作,则自动退出.
-s 不显示用户的输入.记录密码才用.
#基本用法
read -p "请输入密码:" pass
请输入密码:*******'''
echo $pass
*******'''
read -p "请输入密码:" pass
请输入密码:zhongfei123
echo $pass
zhongfei123
不显示用户的输入.
[root@centos7 ~]# read -s -p "请输入密码:" pass
请输入密码:[root@centos7 ~]#
[root@centos7 ~]# echo $pass
zhong
同时向2个变量赋值。
read -p "请输入2个数字num1 num2:" num1 num2
请输入2个数字num1 num2:zhong fei
echo $num1 $num2
zhong fei
案例:用户输入1个字符串,然后进行显示
[root@centos7 scripts]# cat 09.fake_guess.sh
#!/bin/bash
read -s -p "请偷偷的输入你心中所想的内容:" guess
echo ""
sleep 1
echo "我与你心连心,心有灵犀一点通"
sleep 2
echo "我似乎知道你想的内容了"
sleep 3
echo "是不是这个: $guess"
字符串处理
获取字符串长度
# VAR='hello world!'
# echo $VAR
hello world!
# echo ${#VAR}
12
字符串切片
格式:
${parameter:offset}
${parameter:offset:length}
截取 hello 字符串:
# VAR='hello world!'
# echo ${VAR:0:5}
hello
截取 wo 字符:
# echo ${VAR:6:2}
wo
截取 world!字符串:
# echo ${VAR:5}
world!
截取最后一个字符:
# echo ${VAR:(-1)}
!
截取最后二个字符:
# echo ${VAR:(-2)}
d!
截取从倒数第 3 个字符后的 2 个字符:
# echo ${VAR:(-3):2}
ld
替换字符串
格式:${parameter/pattern/string}
${变量名/要替换谁/替换成什么}
# VAR='hello world world!'
将第一个 world 字符串替换为 WORLD:
# echo ${VAR/world/WORLD}
hello WORLD world!
将全部 world 字符串替换为 WORLD:
# echo ${VAR//world/WORLD}
hello WORLD WORLD!
替换正则匹配为空:
# VAR=123abc
# echo ${VAR//[^0-9]/}
123
# echo ${VAR//[0-9]/}
abc
pattern 前面开头一个正斜杠为只匹配第一个字符串,两个正斜杠为匹配所有字符。
字符串截取
格式:
${parameter#word} #从变量左边开始删除,按照最短匹配删除
${parameter##word} #从变量左边开始删除,按照最长匹配删除
${parameter%word} # 从变量右边开始删除,按照最短匹配删除
${parameter%%word} #从变量右边开始删除,按照最长匹配删除
# 去掉左边,最短匹配模式,##最长匹配模式。
% 去掉右边,最短匹配模式,%%最长匹配模式。
# URL="http://www.baidu.com/baike/user.html"
以//为分隔符截取右边字符串:
# echo ${URL#*//}
www.baidu.com/baike/user.html
以/为分隔符截取右边字符串:
# echo ${URL##*/}
user.html
以//为分隔符截取左边字符串:
# echo ${URL%%//*}
http:
以/为分隔符截取左边字符串:
# echo ${URL%/*}
http://www.baidu.com/baike
以.为分隔符截取左边:
# echo ${URL%.*}
http://www.baidu.com/baike/user
以.为分隔符截取右边:
# echo ${URL##*.}
html
变量状态赋值
${VAR:-string} 如果 VAR 变量为空则返回 string
${VAR:+string} 如果 VAR 变量不为空则返回 string
${VAR:=string} 如果 VAR 变量为空则重新赋值 VAR 变量值为 string
${VAR:?string} 如果 VAR 变量为空则将 string 输出到 stderr
例:如果变量不为空就返回 hello world!: # VAR="hello"
# echo ${VAR:+'hello world!'}
hello world!
如果变量为空就重新赋值:
# VAR=
# echo ${VAR:=hello}
hello
# echo $VAR
hello
如果变量为空就将信息输出 stderr: # VAR=
# echo ${VAR:?value is null}
-bash: VAR: value is null
字符串颜色
https://blog.csdn.net/yetugeng/article/details/89978787
Shell 表达式与运算符
整数比较符
比较符 描述 示例
-eq,equal 等于 [ 1 -eq 1 ]为 true
-ne,not equal 不等于 [ 1 -ne 1 ]为 false
-gt,greater than 大于[ 2 -gt 1 ]为 true
-lt,lesser than 小于 [ 2 -lt 1 ]为 false
-ge,greater or equal 大于或等于 [ 2 -ge 1 ]为 true
-le,lesser or equal 小于或等于 [ 2 -le 1 ]为 false
#示例:测试一下 10 是否大于 10 以及 10 是否等于 10(通过输出的返回值内容来判断):
[root@shell ~]# [ 10 -gt 10 ]
[root@shell ~]# echo $?
1
[root@shell ~]# [ 10 -eq 10 ]
[root@shell ~]# echo $?
0
字符串比较符
运算符
|
描述
|
示例
|
==
|
等于
|
[ "a" == "a" ]为 true
|
!=
|
不等于
|
[ "a" != "a" ]为 false
|
<=
|
小于等于
|
在(())表达式中:(( 3 <= 2 ))为 false
|
>=
|
大于等于
|
在(())表达式中:(( 3 >= 2 ))为 true
|
-n
|
字符串长度不等于 0 为真
|
VAR1=1;VAR2=""
[ -n "$VAR1" ]为 true
|
-z
|
字符串长度等于 0 为真
|
VAR1=1;VAR2=""
[ -z "$VAR1" ]为 false
|
str
|
字符串存在为真
|
VAR1=1;VAR2=""
[ $VAR1 ]为 true
|
||
|
或者
|
[ -z $a ] && echo yes || echo no
|
# [ -z $a ] && echo yes || echo no
yes
# [ -n $a ] && echo yes || echo no
yes
# 加了双引号才能正常判断是否为空
# [ -z "$a" ] && echo yes || echo no
yes
# [ -n "$a" ] && echo yes || echo no
no
# 使用了双中括号就不用了双引号
# [[ -n $a ]] && echo yes || echo no
no
# [[ -z $a ]] && echo yes || echo no
yes
文件测试
测试符 描述
-e 文件或目录存在为真 [ -e path ] path 存在为 true
-f 文件存在为真 [ -f file_path ] 文件存在为 true
-d 目录存在为真 [ -d dir_path ] 目录存在为 true
-r 有读权限为真[ -r file_path ] file_path 有读权限为 true
-w 有写权限为真[ -w file_path ] file_path 有写权限为 true
-x 有执行权限为真 [ -x file_path ] file_path 有执行权限为 true
-s 文件存在并且大小大于0为真 [ -s file_path ] file_path 存在并且大小大于 0为true
#判断/etc/fstab 是否为一个目录类型的文件
[root@shell ~]# [ -d /etc/fstab ]
[root@shell ~]# echo $?
1
#判断/etc/fstab是否为一般文件,如果返回值为0,则代表文件存在,反之
[root@shell ~]# [ -f /etc/fstab ]
[root@shell ~]# echo $?
0
布尔运算符
运算符
|
描述
|
示例
|
!
|
非关系,取反
|
[ ! 1 -eq 2 ]为 true
|
-a
|
和关系,在【】表达式中使用
|
[ 1 -eq 1 -a 2 -eq 2 ]为 true
|
-o
|
或关系,在【】表达式中使用
|
[ 1 -eq 1 -o 2 -eq 1 ]为 true
|
逻辑判断符
判断符
|
描述
|
示例
|
&&
|
逻辑和,在[[]]和(())表达式中或判断表达
式是否为真时使用
|
[[ 1 -eq 1 && 2 -eq 2 ]]为 true
(( 1 == 1 && 2 == 2 ))为 true
[ 1 -eq 1 ] && echo yes 如果&&前面表达式
为 true 则执行后面的
|
||
|
逻辑或,在[[]]和(())表达式中或判断表达
式是否为真时使用
|
[[ 1 -eq 1 ||2 -eq 1 ]]为 true
(( 1 == 1 ||2 == 2 ))为 true
[ 1 -eq 2 ] ||echo yes 如果||前面表达式为
false 则执行后面的
|
整数运算
运算符 描述
+ 加法
- 减法
* 乘法
/ 除法
%取余
运算表达式 :
$(())$((1=1))
$[ ] $[1+1]
$(())表达式还有一个用途,三目运算:
在此处所谓的单双,指的是参与运算的运算数个数。
单目运算
* 如大多数编程语言中都有的 i++、i-- 就是一种典型的单目运算。逻辑运算中的“非”运算,即 !a
,也是一种单目运算。
二目运算
* 二目运算同理,a + b , a - b , a ∩ b 等等
三目运算
* 三目运算稍复杂一些,下面给出一个表达式然后尽量通俗的解释:
status = hungry ? eat : notEat
这个表达式可以理解成:
* 肚子饿吗?
* 如果饿的话(status = hungry),就去吃饭。
* 如果不饿 (status != hungry),就不吃了。
* 参与运算的运算数有:hungry、eat、notEat三个。
# 如果条件为真返回 1,否则返回 0
# echo $((1<0))
0
# echo $((1>0))
1
指定输出数字:
# echo $((1>0?1:2))
1
# echo $((1<0?1:2))
2
注意:返回值不支持字符串
其他运算工具(let/expr/bc)
let
赋值并运算,支持++、--
例:
let VAR=(1+2)*3 ;
echo $VAR
x=10 ; y=5
let x++;echo $x 每执行一次 x 加 1
let y--;echo $y 每执行一次 y 减 1
let x+=2 每执行一次 x 加 2
let x-=2 每执行一次 x 减 2
expr
乘法*需要加反斜杠转义*
例:
expr 1 * 2 运算符两边必须有空格
expr ( 1 + 2 ) * 2 使用双括号时要转义
bc
计算器,支持浮点运算、平方等
例:
bc 本身就是一个计算器,可直接输入命令,进入解释器。
echo 1 + 2 |bc 将管道符前面标准输出作为 bc 的标准输入
echo "1.2+2" |bc
echo "10^10" |bc
echo 'scale=2;10/3' |bc 用 scale 保留两位小数点
由于 Shell 不支持浮点数比较,可以借助 bc 来完成需求:
# echo "1.2 < 2" |bc
1
# echo "1.2 > 2" |bc
0
# echo "1.2 == 2.2" |bc
0
# echo "1.2 != 2.2" |bc
1
看出规律了嘛?运算如果为真返回 1,否则返回 0,写一个例子:
# [ $(echo "2.2 > 2" |bc) -eq 1 ] && echo yes || echo no
yes
# [ $(echo "2.2 < 2" |bc) -eq 1 ] && echo yes || echo no
no
expr 还可以对字符串操作:
获取字符串长度:
# expr length "string"
6
截取字符串:
# expr substr "string" 4 6
ing
获取字符在字符串中出现的位置:
# expr index "string" str
1
# expr index "string" i
4
获取字符串开始字符出现的长度:
# expr match "string" s.*
6
# expr match "string" str
3
Shell 括号用途总结
( )
用途 1:在运算中,先计算小括号里面的内容
用途 2:数组
用途 3:匹配分组
(( ))
用途 1:表达式,不支持-eq 这类的运算符。不支持-a 和-o,支持<=、>=、<、>这类
比较符和&&、||
用途 2:C 语言风格的 for(())表达式
$( )
执行 Shell 命令,与反撇号等效
$(( ))
用途 1:简单算数运算
用途 2:支持三目运算符 $(( 表达式?数字:数字 ))
[ ]
条件表达式,里面不支持逻辑判断符,比如&& || 不支持
[[ ]]
条件表达式,里面不支持-a 和-o,不支持<=和>=比较符,支持-eq、<、>这类比较符。支持=~模式匹
配,也可以不用双引号也不会影响原意,比[]更加通用
$[ ]
简单算数运算
{ }
对逗号(,)和点点(...)起作用,比如 touch {1,2}创建 1 和 2 文件,touch {1..3}创建 1、
2 和 3 文件
${ }
用途 1:引用变量
用途 2:字符串处理
shell流程控制
if语句
单分支
if [条件表达式]
then
命令
fi
[root@centos7 ~]# vim if1.sh
#!/bin/bash
if [ -d /etc ]
then
echo "is a directory"
fi
[root@centos7 ~]# bash if1.sh
is a directory
##优化
[root@centos7 ~]# vim if1.sh
#!/bin/bash
DIR1="/etc"
if [ -d $DIR1 ]
then
echo "$DIR1 is a directory"
fi
[root@centos7 ~]# bash if1.sh
/etc is a directory
双分支
if [条件表达式]
then
命令。。
else
命令
fi
##编写脚本
[root@centos7 ~]# vim if3.sh
#!/bin/bash
NUM=`ps -ef | grep httpd | grep -vc grep` ##把该服务产生的进程数量显示出来赋值给变量NUM
if [ $NUM -ge 1 ] ##判断进程数量是否大于等于1(如果大于等于
1说明,服务是启动的)
then ##然后
echo "service is running" ##显示服务正在运行
else ##除此之外
echo "service is down" ##显示服务是关闭的
fi #结束
[root@centos7 ~]# bash if3.sh
service is running
##优化脚本,优化后,后续只需要对应的修改SER变量对应的值即可,想判断哪个服务就写哪个服务名
[root@centos7 ~]# vim if3.sh
#!/bin/bash
SER=nfs
NUM=`ps -ef | grep $SER | grep -vc grep`
if [ $NUM -ge 1 ]
then
echo "$SER service is running"
else
echo "$SER service is down"
fi
##方法二
[root@centos7 ~]# vim httpd.sh
#!/bin/bash
SER2=httpd
systemctl status $SER2 &> /dev/null
if [ $? -eq 0 ]
then
echo "$SER2 is running"
else
echo "$SER2 is not running"
fi
[root@centos7 ~]# chmod +x httpd.sh
[root@centos7 ~]# ./httpd.sh
httpd is running
##方法三:
[root@centos7 ~]# vim http1.sh
#!/bin/bash
if systemctl status httpd &> /dev/null
then
echo "service is running"
else
echo "service is down"
fi
[root@centos7 ~]# ./http1.sh
service is running
多分支
if 条件表达式
then
命令
elif 条件表达式
then
命令
else
命令
fi
发送邮件
dnf -y install postfix s-nail
vim /etc/s-nail.rc
#在文件最后添加
set from=295255180@qq.com #你的邮箱
set smtp=smtp.qq.com
set smtp-auth-user=295255180@qq.com #你的邮箱
set smtp-auth-password=gostoxmhcmkzcabb #你的邮箱授权码
set smtp-auth=login
#发送测试邮件
echo "123" | mail -s hihh 你的收件邮箱地址
#发送时候会报错,因为是老版本的写法,但是可以正常用
循环语句
循环for
for 变量名 in 取值列表
do
命令
done
示例:
#!/bin/bash
for i in {1..3}
do
echo $i
done
for 的语法也可以这么写:
#!/bin/bash
for i in "$@" # $@是将位置参数作为单个来处理
{
echo $i
}
# bash test.sh 1 2 3
1
2
3
默认 for 循环的取值列表是以空白符分隔,即系统变量里的$IFS:
#!/bin/bash
for i in 12 34
do
echo $i
done
# bash test.sh
12
34
以命令结果作为列表
#!/bin/bash
for file in $(ls) 这里可以写成`ls`
do
echo $file
done
如果想指定分隔符,可以重新赋值$IFS 变量:
#!/bin/bash
OLD_IFS=$IFS
IFS=":"
for i in $(head -1 /etc/passwd)
do
echo $i
done
IFS=$OLD_IFS # 恢复默认值
# bash test.sh
root
x
00
root
/root
/bin/bash
for 循环还有一种 C 语言风格的语法,常用于计数、打印数字序列:for (( expr1 ; expr2 ; expr3 )) ; do list ;done
#!/bin/bash
for ((i=1;i<=5;i++)) # 也可以 i--
do
echo $i
done
例:
for ((zf=1;zf<10;zf=zf+2))
do
echo $zf
done
或
#!/bin/bash
for var in {1..9..2}
do
echo $var
done
这种叫做for语句的步长,也就是循环变量每次增加的值都是相同数值的时候使用
示例 1:检查多个主机是否存活
#!/bin/bash
for ip in 192.168.1.{1..254}
do
if ping -c 1 $ip >/dev/null
then
echo "$ip OK."
else
echo "$ip NO!"
fi
done
示例2:99乘法表
#!/bin/bash
for((i=1;i<10;i=i+1)) ##可以写成i=i+1或者i++
do
for((j=1;j<=i;j=j+1))
do
echo -n -e " $i*$jt"
done
echo " "
done
#!/bin/bash
for ((i=1;i<=9;i++))
do
for ((j=1;j<=i;j++))
do
let "s=i*j"
echo -ne "$j*$i=$st"
done
echo ""
done
示例3:例计算1+2+3....+100的值。
#!/bin/bash
sum=0
for bl in {1..100}
do
let sum=sum+$bl
done
echo $sum
示例4:计算1+3+5+。。到100的值,间隔2
#!/bin/bash
sum=0
for bl in {1..100..2}
do
let sum=sum+$bl
done
echo $sum
示例5:从列表文件中读取多个用户名,然后为其逐一创建用户账户并设置密码。首先创建用户名称的列表文件users.txt,每个用户名称单独一行。
vim users.txt
harry
jack
marry
angle
bob
[root@zhong ~]# vim creteuser.sh
#!/bin/bash
read -p "Enter The Users Password : " PASSWD
for UNAME in `cat users.txt`
do
id $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Already exists"
else
useradd $UNAME &> /dev/null
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "$UNAME , Create success"
else
echo "$UNAME , Create failure"
fi
fi
done
示例6:让脚本从文本中自动读取主机列表,然后自动逐个测试这些主机是否在线。
[root@zhong ~]# vim ipadds.txt
192.168.1.10
192.168.1.11
192.168.1.12
[root@zhong ~]# vim checkhosts.sh
#!/bin/bash
HLIST=$(cat ~/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ]
then
echo "Host $IP is On-line."
else
echo "Host $IP is Off-line."
fi
done
示例7:面试题,计算1+2+3+...+100 的结果
[root@centos8 ~]#sum=0;for i in {1..100};do let sum+=i;done ;echo sum=$sum
sum=5050
[root@centos8 ~]#seq -s+ 100|bc5050
5050
[root@centos8 ~]#echo {1..100}|tr ' ' +|bc
5050
[root@centos8 ~]#seq 100|paste -sd +|bc
5050
示例8: 100以内的奇数之和
[root@centos8 ~]#sum=0;for i in {1..100..2};do let sum+=i;done;echo sum=$sum
sum=2500
[root@centos8 ~]#seq -s+ 1 2 100| bc
2500
[root@centos8 ~]#echo {1..100..2}|tr ' ' + | bc
2500
示例9: 批量创建用户
[root@centos8 ~]#cat createuser.sh
#!/bin/bash
[ $# -eq 0 ] && { echo "Usage: createuser.sh USERNAME ..." ;exit 1 ; }
for user ;do
id $user &> /dev/null && echo $user is exist || { useradd $user ; echo
$user
is created; }
done
示例10: 批量创建用户和并设置随机密码
[root@centos8 script]#cat user_for.sh
#!/bin/bash
for i in {1..10};do
useradd user$i
PASS=`cat /dev/urandom | tr -dc '[:alnum:]' |head -c12`
echo $PASS | passwd --stdin user$i &> /dev/null
echo user$i:$PASS >> /data/user.log
echo "user$i is created"
done
示例11: 九九乘法表
[root@centos8 script]#cat 9x9_for.sh
#!/bin/bash
for i in {1..9};do
for j in `seq $i`;do
echo -e "${j}x${i}=$[j*i]tc"
done
echo
done
示例12:99乘法表实现过程
#思路
步骤一:
99乘法表中开始为1x1=1,最后的值为 9x9=81,所以需要两个变量i,j。且i和j的值由1都变为i,并
且做了乘法运算。
#!/bin/bash
#99
for i in {1..9}
do
for j in {1..9}
do
echo "$i*$j=$[i*j]"
done
done
#执行结果,不是我们想要的。首先运算结果上有很多冗余数据,其次显示视图不符合要求
步骤二:删除冗余数据
分析可知,冗余数据出现在每次i都循环了9次。如果使得j<=i时,便不会出现冗余数据
#!/bin/bash
#99
for i in {1..9}
do
for j in {1..9}
do
if [ $j -le $i ];then
echo "$j*$i=$[i*j]"
fi
done
done
由执行结果可以看出,冗余数据已经被删除。但是结果并未分为9行。
#步骤三:分行处理,只需要在内层循环结束时,输出一个空行。
#!/bin/bash
#99
for i in {1..9}
do
for j in {1..9}
do
if [ $j -le $i ];then
echo "$j*$i=$[i*j]"
fi
done
echo
done
由图可知,目前分行已经基本ok,但是我们希望每一列数能单独在一行,而不是分为好几行。
#步骤四:取消每次循环换行 echo -n
#!/bin/bash
#99
for i in {1..9}
do
for j in {1..9}
do
if [ $j -le $i ];then
echo -n "$j*$i=$[i*j]"
fi
done
echo
done
由图可知,基本上已经实现了我们的需求。但是看起来仍不太美观。
#步骤五:echo -e t。加入制表符,使结果更加美观。空格也可以,但是会出现不能对齐的效果
#!/bin/bash
#99
for i in {1..9}
do
for j in {1..9}
do
if [ $j -le $i ];then
echo -n -e "$j*$i=$[i*j]t"
fi
done
echo
done