Linux中shell编程

发布于:2025-06-05 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、Shell编程

1.1 常用符号解读

后台执行

简介

& 就是将一个命令从前台转到后台执行,使用格式如下:
	命令 &

示例:

后台执行休眠命令
[root@localhost ~]# sleep 10 &

就是开启这个服务让其在后台运行,你可以继续在当前终端操作,不卡顿

信息符号

信息简介

1 表示正确输出的信息
2 表示错误输出的信息
2>&1 代表所有输出的信息,也可以简写为 "&>"

示例1 - 符号演示:

标准正确输出重定向到zhengque文件
[root@localhost ~]# ls 1>> zhengque 

标准错误输出重定向到errfile文件
[root@localhost ~]# ls 2>> errfile

示例2 - 综合演练

脚本文件内容
[root@localhost ~]# vim ceshi.sh

-- 编辑ceshi.sh文件
#!/bin/bash
# 输出正确信息
echo '下一条错误命令'
# 执行错误命令,输出错误信息
dsfsafsafdsa

1 和 2 综合演练
[root@localhost ~]# /bin/bash ceshi.sh 1>> ceshi-ok 2>> ceshi-err
[root@localhost ~]# cat ceshi-ok
下一条错误命令
[root@localhost ~]# cat ceshi-err
ceshi.sh:行5: dsfsafsafdsa: 未找到命令

1.2 EOF原理

编写请假条
[root@localhost ~]# vim qingjiatiao.sh

#!/bin/bash
# EOF演示请假条示例

cat << EOF
                        请假条
王老师:
    我因患急性空腹病,现在需要到火锅理疗,不能到学校上课,
请准假一天。恳请批准!
                                             请假人:李四
                                                 6月1日
EOF

执行脚本示例
[root@localhost ~]# bash qingjiatiao.sh
                        请假条
王老师:
    我因患急性空腹病,现在需要到火锅理疗,不能到学校上课,
请准假一天。恳请批准!
                                             请假人:李四
                                                 6月1日

示例二 - 多行文件输出

定制主机解析名信息
[root@localhost ~]# cat >> cs1 << EOF
10.0.0.13 k8s-master
10.0.0.14 k8s-node1
10.0.0.15 k8s-node2
EOF

演示效果
[root@localhost ~]# cat cs1
10.0.0.13 k8s-master
10.0.0.14 k8s-node1
10.0.0.15 k8s-node2

EOF的使用便于我们同时操作几台终端,简化了操作

1.3 echo解读

基础知识:

OPTIONS:
-n	不要在最后自动换行
-e	若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:

转义字符
\a		发出警告声;
\b		删除前一个字符;
\c		最后不加上换行符号;
\f		换行但光标仍旧停留在原来的位置;
\n		换行且光标移至行首;
\r		光标移至行首,但不换行;
\t		插入tab;
\v		与\f相同;
\		插入\字符;
\0nnn	打印nnn(八进制)所代表的ASCII字符;  备注:数字0  不要理解成字母o
\xNN  	打印NN(十六进制)所代表的ASCII字符;

-–help	显示帮助
-–version显示版本信息

实践1 - 特殊符号的输出

使用 -e 选项启用转义字符的解析
[root@localhost ~]# echo -e "The 2021 State of DevOps Report\n\t- is here"

实践2 - 内容的拼接

使用 -n 选项启用信息输出不换行
[root@localhost ~]# echo -n hello;echo world

1.4 字体颜色

格式解读:

格式如下:
	echo -e "\033[字背景颜色;文字颜色m 字符串\033[0m"
	echo -e "\033[41;36m 显示的内容 \033[0m"
色彩 绿
字体色 30 31 32 33 34 35 36 37
背景色 40 41 42 43 44 45 46 47

结束控制符

最后面控制选项说明
  \033[0m 关闭所有属性          \033[1m 设置高亮度          \033[4m 下划线
  \033[5m 闪烁                 \033[7m 反显                 \033[8m 消隐
注意:
    \033 是八进制的ESCAPE字符,我们可以用 \e 来代替

实践1 - 字体颜色和背景颜色

字体颜色示例
echo -e "\033[30m 黑色字 \033[31m 红色字 \033[32m 绿色字 \033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[35m 紫色字 \033[36m 天蓝字 \033[37m 白色字 \033[0m"
 
背景颜色示例
echo -e "\033[40;37m 黑底白字 \033[41;37m 红底白字 \033[42;37m 绿底白字 \033[0m"
echo -e "\033[43;37m 黄底白字 \033[44;37m 蓝底白字 \033[45;37m 紫底白字 \033[0m"
echo -e "\033[46;37m 天蓝底白字 \033[47;30m 白底黑字 \033[0m"

示例2:

定制跳板机的测试页面脚本
[root@localhost ~]# vim simple_jumpserver.sh
#!/bin/bash
# 功能:定制跳板机的展示页面
# 作者:wangshuji
# 版本:V0.1
# 联系:superopsmsb.com

echo -e "\e[31m \t\t 欢迎使用跳板机"

echo -e "\e[32m
-----------请选择你要登录的远程主机-----------
 1: 10.0.0.14 (nginx)
 2: 10.0.0.15 (tomcat)
 3: 10.0.0.19 (apache)
 q: 使用本地主机
----------------------------------------------
"'\033[0m'
echo -e "请输入您要选择的远程主机编号: "

1.5 printf格式化

基本语法

printf: printf [-v var] 格式 [参数]

格式化替换符
    %s         字符串
    %d,%i     十进制整数
    %f         浮点格式
    %c         ASCII字符,即显示对应参数的第一个字符
    %b         相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
    %o         八进制值
    %u         不带正负号的十进制值
    %x         十六进制值(a-f)
    %X         十六进制值(A-F)
    %%         表示%本身

格式化转义符号
    \a        警告字符,通常为ASCII的BEL字符
    \b        后退
    \c        抑制(不显示)输出结果中任何结尾的换行字符
    \f        换页(formfeed)
    \n        换行
    \r        回车(Carriage return)
    \t        水平制表符
    \v        垂直制表符
    \\        一个字面上的反斜杠字符
    \ddd    表示1到3位数八进制值的字符。仅在格式字符串中有效
    \0ddd    表示1到3位的八进制值字符

格式化字符解释
–        将字段里已格式化的值向左对齐
空格       在正值前置一个空格,在负值前置一个负号
+        总是在数值之前放置一个正号或负号,即便是正值也是
#        下列形式选择其一:
            %o有一个前置的o;                    %x与%X分别前置的0x与0X;
            %e,%E与%f总是在结果中有一个小数点;  %g与%G为没有结尾的零。
0        以零填补输出,而非空白.这仅发生在字段宽度大于转换后的情况

实践1 - 替换符号演示

基本信息演示 - 单引号和双引号效果一样
[root@localhost ~]# printf "姓名:%s, 语文:%d, 数学:%d\n" "张三" 89 98
姓名:张三, 语文:89, 数学:98

注意:
	相关信息会按照顺序依次替换到格式化的替换符位置

数字格式展示
[root@localhost ~]# printf '姓名:%s, 身高:%f米, 体重:%f公斤\n' "张三" 1.7 66
姓名:张三, 身高:1.700000米, 体重:66.000000公斤

[root@localhost ~]# printf '姓名:%s, 身高:%.2f米, 体重:%.1f公斤\n' "张三" 1.7 66
姓名:张三, 身高:1.70米, 体重:66.0公斤
注意:
	通过 %.nf,n代表小数点后面的可显示的位数。

实践2 - 简单格式化

() 用于信息的批量化显示
[root@localhost ~]# printf "(%d %s)\n" 1 张三 2 李四 3 王五
(1 张三)
(2 李四)
(3 王五)

printf默认不携带最后的换行
[root@localhost ~]# printf "(%d %s)  " 1 张三 2 李四 3 王五
(1 张三)  (2 李四)  (3 王五)  [root@localhost ~]#

借助于echo的功能实现换行的效果
[root@localhost ~]# printf "(%d %s)  " 1 张三 2 李四 3 王五; echo
(1 张三)  (2 李四)  (3 王五)

实践4 - 格式化补充

%s字符串格式化
[root@localhost ~]# printf '姓名:%-10s语文:%d, 数学:%d\n' "张三" 89 98 "李四" 87 97

注意:
	%-10s,代表信息后面携带10个空格,便于格式化

%d数字格式补全
[root@localhost ~]# printf "%5d %s\n" 1 张三
    1 张三
[root@localhost ~]# printf "%05d %s\n" 1 张三
00001 张三
[root@localhost ~]# printf "%05d %s\n" 100 张四
00100 张四
注意:
	0的作用就是不用空格补全,而是用0填充,实现格式化

综合案例

学习目标

这一节,我们从 java部署、脚本定制、小结 三个方面来学习。

java部署

-- 创建目录
mkdir /data/{softs,server} -p
[root@localhost ~]# vim /data/scripts/java_install.sh
#!/bin/bash
# 功能: java环境的定制
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制基本信息
JAVA_SOFT='jdk-8u151-linux-x64.tar.gz'
JAVA_DIR='jdk1.8.0_121'
JAVA_NAME='java'
SERVER_HOME='/data/server'
SOFTS_HOME='/data/softs'
RED="echo -e \E[1;31m"
END="\E[0m"

# 安装软件
tar zxvf $SOFTS_HOME/$JAVA_SOFT -C $SERVER_HOME
ln -s $SERVER_HOME/$JAVA_DIR $SERVER_HOME/$JAVA_NAME

# 定制环境变量
cat >> /etc/profile << EOF
export JAVA_HOME=$SERVER_HOME/$JAVA_NAME
export PATH=\$JAVA_HOME/bin:\$PATH
EOF

# 加载java环境变量文件
source /etc/profile

# 检查效果
java -version > /tmp/txt 2>&1
java_version=$(grep version /tmp/txt  | cut -d '"' -f2)

# 信息显示
$RED---------$JAVA_NAME软件运行情况---------$END
printf "\033[32m%s:\033[33m%s\033[0m\n" "java软件版本" $java_version
$RED----------------------------------$END

1.6 脚本交互

read基础

     read                从标准输入读取一行并赋值给特定变量REPLY。
    read answer            从标准输入读取输入并赋值给变量answer。
    read first last        从标准输入读取内容,将第一个单词放到first中,其他内容放在last中。
    read -s passwd        从标准输入读取内容,写入passwd,不输入效果
    read -n n name        从标准输入读取内容,截取n个字符,写入name,超过n个字符,直接退出
    read -p "prompt"    打印提示,等待输入,并将输入存储在REPLY中。
    read -r line        允许输入包含反斜杠。
    read -t second        指定超时时间,默认是秒,整数
    read -d sper        指定输入信息的截止符号

简单实践

示例1:

交互式接收用户信息
[root@localhost ~]# read
nihao-answer

接收用户输入给一个临时变量
[root@localhost ~]# read answer
nihao-answer
[root@localhost ~]# echo $answer
nihao-answer

接收多个信息,按照顺序交给不同的临时变量
[root@localhost ~]# read first last
first-1 last-2 end-3
[root@localhost ~]# echo $first
first-1
[root@localhost ~]# echo $last
last-2 end-3

示例二:

隐式接收用户输入信息
[root@localhost ~]# read -s password
[root@localhost ~]# echo $password
abcdefg

示例三:

通过 -p 参数提示用户输入的信心
[root@localhost ~]# read -p "请输入登录用户名: " user
请输入登录用户名: root
[root@localhost ~]# echo $user
root

示例4-限制用户输入信息

[root@localhost ~]# read -n 6 -p "sss: " aaa
sss: 123456[root@localhost ~]# read -n 6 -p "只接收6个字符,超过自动退出: " string
只接收6个字符,超过自动退出: 123456[root@localhost ~]#
[root@localhost ~]# echo $string
123456
注意:
	-p + -s 的组合会导致不会自动换行,可以结合 echo的方式实现换行

示例5:

[root@localhost ~]# read -t 5 -p "等待5秒后自动退出! " second
等待5秒后自动退出! 4
[root@localhost ~]# echo $second
4
[root@localhost ~]# read -t 5 -p "等待5秒后自动退出! " second
等待5秒后自动退出! [root@localhost ~]#

案例实践:

[root@localhost ~]# vim simple_login.sh
#!/bin/bash
# 功能: 模拟shell登录
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 清屏
clear

# 输出提示信息
echo "---------------------------------"
# 交互输入登陆信息
read -p "请输入用户名:" account
read -s -t30 -p "请输入登录密码:" password
echo
echo "---------------------------------"
# 输出用户输入信息
printf "您输入的用户名:\e[31m%s\e[0m您输入的密码:\e[31m%s\e[0m\n" ${account} ${password}

跳板机实践

[root@localhost ~]# vim simple_jumpserver.sh
#!/bin/bash
# 功能:定制跳板机的展示页面
# 版本:v0.2
# 作者:书记
# 联系:www.superopsmsb.com

# 跳板机的信息提示
echo -e "\e[31m \t\t 欢迎使用跳板机"

echo -e "\e[32m
-----------请选择你要登录的远程主机-----------
 1: 10.0.0.14 (nginx)
 2: 10.0.0.15 (tomcat)
 3: 10.0.0.19 (apache)
 q: 使用本地主机
----------------------------------------------
"'\033[0m'

# 由于暂时没有学习条件判断,所以暂时选择 q
read -p "请输入您要选择的远程主机编号: " host_index
read -p "请输入登录本地主机的用户名: " user

# 远程连接主机
ssh $user@localhost

1.7 运算符

运算符基础

我们从 $[]、let、(())、$(())、小结 五个方面来讲解

格式:

方法1:
    $[计算表达式]
方法2:
    a=$[变量名a+1]

注意:
    这里的表达式可以不是一个整体

简单示例:

简单运算
[root@localhost ~]# echo $[100/5]
20
[root@localhost ~]# echo $[ 2 + 5 ]
7

变量参与运算
[root@localhost ~]# a=6
[root@localhost ~]# a=$[a+1]
[root@localhost ~]# echo $a
7

运算结果取整
[root@localhost ~]# echo $[100/3]
33

let

格式:

let    变量名a=变量名a+1

注意:
    表达式必须是一个整体,中间不能出现空格等特殊字符

简单示例:

简单运算
[root@localhost ~]# i=1
[root@localhost ~]# let i=i+7
[root@localhost ~]# echo $i
8

let表达式必须是一个整体
[root@localhost ~]# let i = i * 2
bash: let: =: 语法错误: 期待操作数 (错误符号是 "=")
[root@localhost ~]# let i=i * 2
bash: let: anaconda-ks.cfg: 语法错误: 无效的算术运算符 (错误符号是 ".cfg")
[root@localhost ~]# let i=i*2
[root@localhost ~]# echo $i

$(())

格式:

echo $((变量计算表达式))
注意:
    对于 $(())中间的表达式,可以不是一个整体,不受空格的限制

[root@localhost ~]# num1=34
[root@localhost ~]# echo $((num2=num1+34))
68

赋值运算进阶

简单实践

加法运算
[root@localhost ~]# echo $(( 4 + 4 ))
8
[root@localhost ~]# num1=3 num2=4
[root@localhost ~]# echo $(($num1 + $num2))
7

减法运算
[root@localhost ~]# echo $((8-2))
6
[root@localhost ~]# echo $(($num2-$num1))
1

乘法运算
[root@localhost ~]# echo $((8*2))
16
[root@localhost ~]# echo $(($num2*$num1))
12

除法运算
[root@localhost ~]# echo $((8/2))
4
[root@localhost ~]# echo $(($num2/$num1))
1

取余运算
[root@localhost ~]# echo $((8%3))
2
[root@localhost ~]# echo $(($num2%$num1))
1

案例实践-小学计算题

查看脚本内容
[root@localhost ~]# vim count_head_feet.sh
#!/bin/bash
# 功能:小学计算题目
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制普通变量
head="$1"
feet="$2"

# 计算逻辑
# 每个头至少两只脚,多出的脚都是兔子的
rabbit_num=$(( ($feet - $head - $head) / 2))
chick_num=$[ $head - $rabbit_num ]

# 结果输出
echo -e "\e[31m\t鸡和兔的数量\e[0m"
echo -e "\e[32m============================"
echo "鸡的数量: ${chick_num}"
echo "兔的数量:${rabbit_num}"
echo -e "============================\e[0m"

赋值运算

简介

    这里的赋值运算,是一种进阶版本的复制操作,常见的样式如下:
        样式1:+=、-=、*=、/=
            - 在自身的基础上进行二元运算,结果值还是自己
        样式2:++、--
            - 在自身的基础上进行递增和递减操作,结果值还是自己        

简单示例:

+=运算
[root@localhost ~]# num1=6
[root@localhost ~]# let value+=$num1    # 相当于 let value=value+$num1
[root@localhost ~]# echo $value
6

-=运算
[root@localhost ~]# let value-=2    # 相当于 let value=value-2
[root@localhost ~]# echo $value
4

*=运算
[root@localhost ~]# let value*=2    # 相当于 let value=value*2
[root@localhost ~]# echo $value
8

/=运算
[root@localhost ~]# let value/=2    # 相当于 let value=value/2
[root@localhost ~]# echo $value
4
i++运算
[root@localhost ~]# value=9
[root@localhost ~]# let value++		# 相当于 let value=value+1
[root@localhost ~]# echo $value
10
[root@localhost ~]# let value++		# 相当于 let value=value+1
[root@localhost ~]# echo $value
11

++i运算
[root@localhost ~]# let ++value		# 相当于 let value=value+1
[root@localhost ~]# echo $value
12

expr计算

expr即可以做常见的整数运算,还可以做数字比较,字符串计算等操作。

格式:

数字场景:
    expr 运算表达式
字符串场景:
    match:用户获取匹配到字符串的长度
        expr match 字符串 匹配内容
    substr:截取字符串
        expr substr 字符串 起始位置 截取长度
        注意:起始位置值>=1
    index:查找第一次匹配字符的位置
        expr index 字符串 字符
    length:计算字符串的长度
        expr length 字符串 

简单实践

数学运算[root@localhost ~]# expr 1 + 2 - 3 \* 4 / 5 + \( 6 - 7 \) \* 8
-7
[root@localhost ~]# x=1
[root@localhost ~]# expr $x + 4
5

字符串运算

用户获取匹配到字符串的长度
[root@localhost ~]# file=jdslkfajkldsjafklds
[root@localhost ~]# expr match $file "k.*j"
0
[root@localhost ~]# expr match $file ".*j"
13

截取字符串
[root@localhost ~]# expr substr $file 0 4
[root@localhost ~]# expr substr $file 1 4
jdsl

查找第一次匹配字符的位置
[root@localhost ~]# expr index $file b
0
[root@localhost ~]# expr index $file j
1

计算字符串的长度
[root@localhost ~]# expr length $file
19


网站公告

今日签到

点亮在社区的每一天
去签到