[华为云在线课程][Shell脚本编程基础][第三章BashShell配置和流程控制][学习笔记]

举报
John2021 发表于 2022/04/16 15:40:17 2022/04/16
【摘要】 bash shell的配置文件bash shell的配置文件很多,可以分成下面类别 按生效范围划分两类全局配置:针对所有用户皆有效/etc/profile/etc/profile.d/*.sh/etc/bashrc个人配置:只针对特定用户有效~/.bash_profile~/.bashrc shell登录两种方式分类 交互式登录1,直接通过终端输入账号密码登录2,使用su - userna...

bash shell的配置文件

bash shell的配置文件很多,可以分成下面类别

按生效范围划分两类

全局配置:针对所有用户皆有效

/etc/profile
/etc/profile.d/*.sh
/etc/bashrc

个人配置:只针对特定用户有效

~/.bash_profile
~/.bashrc

shell登录两种方式分类

交互式登录

1,直接通过终端输入账号密码登录
2,使用su - username切换用户

配置文件生效和执行顺序

#放在每个文件最前面
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
~/.bash_profile
~/.bashrc
/etc/bashrc

#放在每个文件最后
/etc/profile.d/*.sh
/etc/bashrc
/etc/profile
/etc/bashrc #此文件执行两次

注意:文件之间的调用关系,写在同一个文件的不同位置,将影响文件的执行顺序

非交互式登录

1,su username
2,图形界面下打开的终端
3,执行脚本
4,任何其他的bash示例

执行顺序:

/etc/profile.d/*.sh
/etc/bashrc
~/.bashrc

例子:将命令放在最前面

/etc/profile
/etc/profile.d/test.sh
/etc/bashrc
~/.bash_profile
~/.bashrc
/etc/bashrc

su - root
/etc/profile
/etc/profile.d/test.sh
/etc/bashrc
~/.bash_profile
~/.bashrc
/etc/bashrc

exit
su root
~/.bashrc
/etc/bashrc
/etc/profile.d/test.sh

按功能划分分类

Profile类

profile类为交互式登录的shell提供配置

全局:/etc/profile,/etc/profile.d/*.sh
个人:~/.bash_profile

Bashec类

bashrc类:为非交互式和交互式登录的shell提供配置

全局:/etc/bashrc
个人:~/.bashrc

功能:
1,定义命令别名和函数
2,定义本地变量

编辑配置文件生效

修改profile和bashrc文件后需生效的两种方法:
1,重新启动shell进程
2,source|. 配置文件

注意:source会在当前shell中执行脚本,所有一般只用于执行配置文件,或在脚本中调用另一个脚本的场景
例子:

. ~/.bashrc

bash退出任务

保存在~/.bash_logout文件中(用户),在退出登录shell时运行
功能:创建自动备份,清楚临时文件。

流程控制

条件选项

条件判断介绍

单分支条件

多分支条件

选择执行if语句

例子:身体质量指数(BMI)

[root@localhost code]# cat if_bmi.sh
#!/bin/bash

read -p "请输入身高(m为单位):" HIGH

if [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$  ]];then
    echo "输入错误的身高"
    exit 1
fi

read -p "请输入体重(kg为单位):" WEIGHT

if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$  ]];then
    echo "输入错误的体重"
    exit 1
fi

BMI=`echo $WEIGHT/$HIGH^2|bc`

if [ $BMI -le 18  ];then
    echo "多吃点"
elif [ $BMI -lt 24  ];then
    echo "身材很棒"
else
    echo "太胖了,注意节食,加强运动"
fi

条件判断case语句

格式:

case WORD in [PATTERN [| PATTERN]...] COMMANDS ;;]... esac
case 变量引用 in
PAT1)
    分支1
    ;;
PAT2)
    分支2
    ;;
...
*)
    默认分支
    ;;
esac

case支持glob风格的通配符

*           任意长度任意字符
?           仁义单个字符
[]          指定范围内的任意单个字符
|           或者,如:a|b

例子:

[root@localhost code]# cat case_yesorno.sh
#!/bin/bash
read -p "Do you agree(yes/no)? " INPUT
INPUT=`echo $INPUT | tr 'A-Z' 'a-z'`
case $INPUT in
y|yes)
    echo "You input is YES"
    ;;
n|no)
    echo "You input is NO"
    ;;
*)
    echo "Input fails"
esac

[root@localhost code]# cat case_yesorno2.sh
#!/bin/bash
read -p "Do you agree(yes/no)?" INPUT
case $INPUT in
[Yy]|[Yy][Ee][Ss])
    echo "You input is YES"
    ;;
[Nn]|[Nn][Oo])
    echo "You input is NO"
    ;;
*)
    echo "Input fails."
esac

例子:文件后缀处理

[root@localhost code]# cat suffix.sh
#!/bin/bash
read -p "Please input a file's name: " FILE
SUFFIX=`echo $FILE | grep -Eo "[^.]+$"`
case $SUFFIX in
gz)
    echo gzip
    ;;
bz2)
    echo bzip2
    ;;
xz)
    echo xz
    ;;
Z)
    echo compress
    ;;
zip)
    echo zip
    ;;
*)
    echo other
    ;;
esac

循环

循环执行介绍

将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数

  • 循环次数事先已知
  • 循环次数事先未知

常见的循环的命令:for,while,until

循环for

格式1:

for NAME [in WORDS ...]; do COMMANDS; done
#方式1
for 变量名 in 列表;do
    循环体
done
#方式2
for 变量名 in 列表
do
    循环体
done

执行机制:
1,依次将列表中的元素赋值给"变量名";每次赋值后即执行一次循环体;直到列表中的元素耗尽,循环结束
2,如果省略[in WORDS…],此时使用位置参量

for循环列表生成方式:
1,直接给出列表
2,整数列表:

{start..end}
$(seq [start [step]] end)

3,返回列表的命令

$(COMMAND)

4,使用glob,如:.sh
5,变量引用,如: @ @,
,$#

例子:面试题,计算1+2+3+…+100的结果

[root@localhost code]# sum=0;for i in {1..100};do let sum+=i;done;echo sum=$sum
sum=5050
[root@localhost code]# seq -s+ 100|bc
5050
[root@localhost code]# echo {1..100}|tr ' ' +|bc
5050
[root@localhost code]# seq 100|paste -sd +|bc
5050

例子:100以内的奇数之和

[root@localhost code]# sum=0;for i in {1..100..2};do let sum+=i;done;echo sum=$sum
sum=2500
[root@localhost code]# seq -s+ 1 2 100 | bc
2500
[root@localhost code]# echo {1..100..2}|tr ' '+ |bc
tr: missing operand after ‘ +’
Two strings must be given when translating.
Try 'tr --help' for more information.
[root@localhost code]# echo {1..100..2}|tr ' ' + |bc
2500

例子:

[root@localhost code]# ./for_sum.sh 1 2 3 4
sum=10
[root@localhost code]# cat for_sum.sh
#!/bin/bash
sum=0
for i in $*;do
    let sum+=i
done
echo sum=$sum

例子:批量创建用户和并设置随机密码

[root@localhost code]# cat user_for.sh
#!/bin/bash
for i in {1..5};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 >> /home/hello/users/user.log
    echo "user$i is created"
done

例子:九九乘法表

[root@localhost code]# ./99.sh
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
[root@localhost code]# cat 99.sh
#!/bin/bash
for i in {1..9};do
    for j in `seq $i`;do
        echo -ne "${j}x${i}=$((i*j))\t"
    done
    echo
done

例子:倒叙九九乘法表

[root@localhost code]# ./99_v2.sh
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x4=4   2x4=8   3x4=12  4x4=16
1x3=3   2x3=6   3x3=9
1x2=2   2x2=4
1x1=1
[root@localhost code]# cat 99_v2.sh
#!/bin/bash
for i in {1..9};do
    for j in $(seq `echo $[10-$i]`);do
        echo -ne "${j}x`echo $[10-i]`=$(((10-i)*j))\t"
    done
    echo
done

生产案例:将指定目录下的文件所有文件的后缀更名为bak后缀

[root@localhost code]# cat for_rename.sh
#!/bin/bash
DIR=/data/test
for FILE in *;do
    PRE=`echo $FILE|grep -Eo ".*\."`
    mv $FILE $DIR/${PRE}bak
done

面试题:要求将目录YYYY-MM-DD/中所有文件,移动到YYYY-MM/DD/下

#1,创建YYYY-MM-DD格式的目录,当前日期一年前365天到目前共365个目录,里面有10个文件.log后缀的文件
[root@localhost code]# cat for_dir.sh
#!/bin/bash
PDIR=/home/hello/test
for i in {1..365};do
    DIR=`date -d "-$i day" +%F`
    mkdir -pv $PDIR/$DIR
    cd $PDIR/$DIR
    for j in {1..10};do
        touch $RANDOM.log
    done
done
#2,将上面的目录移动到YYYY-MM/DD/下
[root@localhost code]# cat for_dir1.sh
#!/bin/bash
DIR=/home/hello/test
cd $DIR
for subdir in *;do
    YYYY_MM=`echo $subdir |cut -d"-" -f1,2`
    DD=`echo $subdir |cut -d"-" -f3`
    [ -d $YYYY_MM/$DD  ] || mkdir -p $YYYY_MM/$DD &> /dev/null
    mv $subdir/* $YYYY_MM/$DD
done
rm -rf $DIR/*-*-*

格式2:
双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash shell实现C语言风格的变量操作

for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for ((控制变量初始化;条件判断表达式;控制变量的修正表达式))
do
    循环体
done

说明:
1,控制变量初始化:仅在运行到循环代码段时执行一次
2,控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

例子:

[root@localhost code]# ./sum.sh
sum=5050
[root@localhost code]# cat sum.sh
#!/bin/bash
for((sum=0,i=1;i<=100;sum+=i,i++));do
    true
done
echo sum=$sum

例子:九九乘法表

#语法1实现
[root@localhost code]# ./for_99.sh
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
[root@localhost code]# cat for_99.sh
#!/bin/bash
for i in {1..9};do
    for j in `seq $i`;do
        echo -e "${j}x${i}=$((j*i))\t\c"
    done
    echo
done

#语法2实现
[root@localhost code]# ./for_99_2.sh
1x1=1
1x2=2   2x2=4
1x3=3   2x3=6   3x3=9
1x4=4   2x4=8   3x4=12  4x4=16
1x5=5   2x5=10  3x5=15  4x5=20  5x5=25
1x6=6   2x6=12  3x6=18  4x6=24  5x6=30  6x6=36
1x7=7   2x7=14  3x7=21  4x7=28  5x7=35  6x7=42  7x7=49
1x8=8   2x8=16  3x8=24  4x8=32  5x8=40  6x8=48  7x8=56  8x8=64
1x9=9   2x9=18  3x9=27  4x9=36  5x9=45  6x9=54  7x9=63  8x9=72  9x9=81
[root@localhost code]# cat for_99_2.sh
#!/bin/bash
for((i=1;i<10;i++));do
    for((j=1;j<=i;j++));do
        echo -e "${j}x${i}=$((j*i))\t\c"
    done
    echo
done
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。