Linux从入门到精通(十二)——shell编程
admin
2024-02-11 13:24:38

文章篇幅较长,建议先收藏,防止迷路

文章跳转
Linux从入门到精通(八)——Linux磁盘管理go
Linux从入门到精通(九)——Linux编程go
Linux从入门到精通(十)——进程管理go
Linux从入门到精通(十一)——计划任务go
Linux从入门到精通(十二)——shell编程go

目录

  • shell编程
    • 1. shell和shell脚本
      • 1.1 shell
      • 1.2 shell脚本
    • 2. shell脚本创建和执行方式
    • 3. shell变量
      • 3.1 用户自定义的变量
      • 3.2 位置变量
      • 3.3 预定义变量:
      • 3.2-3 例子:
      • 3.4 环境变量
      • 3.5 变量替换
    • 4. shell基本语法
      • 4.1 read 命令
      • 4.2 echo 显示命令
      • 4.3 数值计算
      • 4.4 变量表达式测试
        • 4.4.1 字符串测试
        • 4.4.2 数值测试
        • 4.4.3 文件测试
        • 4.4.4 逻辑测试
      • 4.5 流程控制语句
        • 4.5.1 If
        • 4.5.2 case
    • 5. 补充

shell编程

1. shell和shell脚本

1.1 shell

  • Shell是一种具备特殊功能的程序,它是介于使用者和UNIX/Linux操作系统之核心程序 ( kernel) 之间的一个接口。
  • 为了对用户屏蔽内核的复杂性,也为了保护内核 以免用户误操作造成损害,在内核的周围建立了一个外壳( shell ) 用户向shell提出要求 ,shell解释并将请求传给内核。
  • 查看当前环境所使用的shell : echo $SHELL, 每个用户的缺省shell在系统里的/etc/passwd 文件里被指定。

常见的shell:

  • Bourne Shell (简称sh) :由AT&T贝尔实验室的 Steven. Bourne开发。目前几乎所有的Linux系统 都支持它,将其作为应急Shell使用。
  • C Shell (简称csh) :C Shell由加利福尼亚大学 伯克利分校开发。编程风格类似于C语言,健壮性不 如Bourne Shell。
  • Korn Shell (简称 ksh) :与Bourne Shell向下完全兼容。Korn Shell 的效率很高,其命令交互界面和编程交互界面都很好。
  • Bourne Again Shell ( 简称bash ) :是Bourne Shell 的增强版,已经成为最流行的Shell。能够提供环境变量以配置用户Shell环境, 支持历史记录,内置算术功能,支持通配符表达式,将常用命令内置简化。

1.2 shell脚本

Shell脚本:按照一定的语法结构把若干linux命令组合在一起,实现特定的功能。

  • Shell 脚本是纯文本文件。
  • Shell 脚本通常以.sh 作为后缀名,但不是必须。
  • Shell脚本是以行为单位的,在执行脚本的时候会分解成一 行一行依次执行。

2. shell脚本创建和执行方式

shell结构:

  1. 第一行一定要指明系统需要那种Shell解释用户的shell 程序, 如# !/bin/sh ,#!/bin/bash
  2. #注释行
  3. 命令和控制结构

创建shell程序的步骤:

  1. 创建一个包含命令和控制结构的文件。

  2. 修改这个文件的权限,使它可以执行。

    chmod u+x
    
  3. 执行

    ./xxxx.sh
    # 或者:
    bash xxxx.sh
    

3. shell变量

像高级程序设计语言一样,Shell也提供说明和使用变量的功能。

Shell只要有以下4种变量:

  1. 用户自定义的变量;
  2. 位置变量;
  3. 预定义变量;
  4. 环境变量;

3.1 用户自定义的变量

用户自定义变量名由字母和下划线组成,并且变量名第一个字母不能为数字。

用户自定义变量定义:

变量名=变量值

注意事项:

  • 变量不需声明,可直接使用或者赋值

  • 在给变量赋值时,等号两边一定不能留空格,若变量中本身就包含了空格,则整个字符串都要用双引号括起来。

  • 查看所有的变量,可以使用set命令;

    [root@localhost hadoop]# SUN=sun
    [root@localhost hadoop]# set|grep SUN
    SUN=sun
    
  • 使用变量时,可以在变量名前面加一个美元符号$。建议在变量名字两边$后面加上{};

    [root@localhost hadoop]# echo ${SUN}
    sun
    [root@localhost hadoop]# echo ${SUN}day
    sunday
    [root@localhost hadoop]# echo $SUNday
    # 空
    
  • 使用readonly命令可以将变量定义为只读变量。

    readonly ABC=aaa
    
  • 清除变量:

    unset 变量名unset SUN
    
  • 三种特殊符号:

    1. ``反引号:执行反引号中命令,将结果赋给变量。
    2. ’‘单引号:原封不动的输出
    3. “” 双引号:括起来的字符除美元符号($)、反斜杠(\) 、反引号(`) 和双引号(")之外都将作为普通字符对待。
    [root@localhost hadoop]# H1=hello
    [root@localhost hadoop]# W1='${H1},world
    [root@localhost hadoop]# W2="${H1},world"
    [root@localhost hadoop]# echo ${W1}
    ${H1},world
    [root@localhost hadoop]# echo ${W2}
    hello,world[root@localhost etc]# ll
    总用量 4
    drwxr-xr-x. 2 huyuyang huyuyang 4096 11月 23 13:44 hadoop
    [root@localhost etc]# W3=`ll`
    [root@localhost etc]# echo ${W3}
    总用量 4 drwxr-xr-x. 2 huyuyang huyuyang 4096 11月 23 13:44 hadoop
    

3.2 位置变量

​ 位置参数是一种在调用Shell程序的命令行中按照各自的位置决定的变量,是在程序名之后输入的参数。$0是一个比较特殊的位置参数,用于表示脚本自己的文件名。

  • $0:脚本程序的名字。
  • $1,$2...$9:传递给脚本的某个参数,$1 代表第1个参数, $2代表第2个参数,依此类推。

例子和预定义变量一起;

3.3 预定义变量:

预定义变量是在Shell一开始时就定义了的变量,由符号$和另一个符号组成的,只能使用,不能修改。

  • $#:传递到脚本的参数的数量;
  • $*:以"参数1参数2… "形式保存所有参数;
  • $@:以"参数1" “参数2” …形式保存所有参数;
  • $?:命令执行后返回的状态,0表示成功执行,其他值则表明执行错误;
  • $$:当前进程的进程号 ;
  • $!:后台运行的最后一个进程号;

3.2-3 例子:

[root@VM-24-17-centos shellstudy]# cat test.sh
#!/bin/bash
# 学习位置变量与预定义变量
echo '$# is:' $#
echo '$* is:' $*
echo '$? is:' $?
echo '$$ is:' $$
echo '$@ is:' $@
echo '$0 is:' $0
echo '$2 is:' $2
# 使test.sh拥有执行权限
[root@VM-24-17-centos shellstudy]# chmod u+x test.sh
[root@VM-24-17-centos shellstudy]# ./test.sh p1 p2 p3 p4
$# is: 4
$* is: p1 p2 p3 p4
$? is: 0
$$ is: 200606
$@ is: p1 p2 p3 p4
$0 is: ./test.sh
$2 is: p2

3.4 环境变量

环境变量又称全局变量, 通常,由系统在启动时设置,环境变量一般用大写字母表示。

  1. 查看环境变量:env

    [root@VM-24-17-centos shellstudy]# env | grep JAVA_HOME
    JAVA_HOME=/usr/local/applications/java/jdk1.8.0_221
    CLASSPATH=%JAVA_HOME%/lib:%JAVA_HOME%/jre/lib
    
  2. 使用export命令将变量添加到环境中, 作为临时的环境变量(一种全局变量)。

    [root@VM-24-17-centos shellstudy]# env | grep EMAIL
    [root@VM-24-17-centos shellstudy]# export EMAIL=2582952862@qq.com
    [root@VM-24-17-centos shellstudy]# env | grep EMAIL
    EMAIL=2582952862@qq.com
    

3.5 变量替换

可以使用以下几种变量替换形式(replacevar.sh):

  • ${var}:替换为变量本来的值。

  • ${var:-word}:如果变量var为空或已被删除,则返word,但不改变var的值。

    [root@VM-24-17-centos shellstudy]# echo ${SUN}
    # 空
    [root@VM-24-17-centos shellstudy]# echo ${SUN:-word}
    word
    [root@VM-24-17-centos shellstudy]# echo ${SUN}
    # 空
    
  • ${var:+word}:如果变量var被定义,则返word,但不改变var的值。

  • ${var:=word}:如果变量var为空或已被删除,则返word,并将变量var的值设置为word。

  • ${var:?message}:如果变量var为空或已被删除,则将消息message发送到标准输出错误中,可以用来检测变量var是否可以被正常赋值。这种替换出现在shell脚本中,脚本将停止运行。

    [root@VM-24-17-centos shellstudy]# echo ${SUN:?hyy}
    -bash: SUN: hyy
    

【例子1】

[root@VM-24-17-centos shellstudy]# vim replacevar.sh
#!/bin/bash
username=hyy
a=${username:-`whoami`}
b=${username:+`whoami`}
c=${username:=`whoami`}
echo "username=${username} a=${a}"
echo "username=${username} b=${b}"
echo "username=${username} c=${c}"
echo "now, unsert username"
unset username
a=${username:-`whoami`}
echo "username=${username} a=${a}"
b=${username:+`whoami`}
echo "username=${username} b=${b}"
c=${username:=`whoami`}
[root@VM-24-17-centos shellstudy]# chmod u+x replacevar.sh
[root@VM-24-17-centos shellstudy]# ./replacevar.sh 
username=hyy a=hyy
username=hyy b=root
username=hyy c=hyy
now, unsert username
username= a=root
username= b=
username=root c=root[root@VM-24-17-centos shellstudy]# echo ${SUN:?'var:SUN not exist'}
-bash: SUN: var:SUN not exist

另外也可以通过如下操作取变量内容(modvar.sh)
准备:

[root@VM-24-17-centos shellstudy]# var=/dirl/dir2/file.txt
  1. 求字符串的长度

    [root@VM-24-17-centos shellstudy]# echo ${#var}
    19
    
  2. 提取位置3到最后的字符

    [root@VM-24-17-centos shellstudy]# echo ${var:3}
    rl/dir2/file.txt
    
  3. 从位置3,开始提取5个字符

    [root@VM-24-17-centos shellstudy]# echo ${var:3:5}
    rl/di
    
  4. 从左边开始,删除最短匹配ir

    [root@VM-24-17-centos shellstudy]# echo ${var#*ir}
    l/dir2/file.txt
    
  5. 从左边开始, 删除最长匹配ir,这里的*表示删除

    [root@VM-24-17-centos shellstudy]# echo ${var##*ir}
    2/file.txt
    
  6. 从右边开始,删除最短匹配di,注意:这里的*在后面。

    [root@VM-24-17-centos shellstudy]# echo ${var%di*}
    /dirl/
    
  7. 从右边开始, 删除最长匹配di

[root@VM-24-17-centos shellstudy]# echo ${var%%di*}
/
  1. 用yst替换第一个匹配的root,如果需要把/替换掉,需要加转义字符\

    [root@VM-24-17-centos shellstudy]# echo ${var/dir/yst}
    /ystl/dir2/file.txt
    

【例子2】

[root@VM-24-17-centos shellstudy]# vim modvar.sh
#!/bin/bash
var=/dirl/dir2/file.txt
echo ${#var}
echo ${var:3}
echo ${var:3:5}
echo ${var#*ir}
echo ${var##*ir}
echo ${var%di*}
echo ${var%%di*}
echo ${var/dir/yst}
unset var
[root@VM-24-17-centos shellstudy]# chmod u+x modvar.sh 
[root@VM-24-17-centos shellstudy]# ./modvar.sh 
19
rl/dir2/file.txt
rl/di
l/dir2/file.txt
2/file.txt
/dirl/
/
/ystl/dir2/file.txt

4. shell基本语法

​ 在shell中使用read命令从标准输入读入数据, 并将该数据赋值给变量;使用echo命令实现换行标 准输出操作。

​ 在进行计算整数变量值时,可以使用expr表达式let命令$()形式$[]形式实现。

​ test是Shell程序中的一个表达式,通过和Shell 提供的if等条件语句相结合可以方便地测试字符串、 文件状态和数字。

4.1 read 命令

read命令可以通过键盘输入为变量赋值:

read[参数]变量名...

  • -p后面跟提示信息,即在输入前打印提示信息。

  • -n后跟一个数字,指定输入文本的长度,当输入的字符数目达到预定数目时,自动退出,并将输入的数据赋值给变量。

  • -S输入字符时不在屏幕上显示

  • read读入的变量可以有多个,第一个数据给第一个变量,第二个数据给第二个变量,如果输入数据个数过多,则最后所有的值都给最后一个变量。

    [root@VM-24-17-centos shellstudy]# read a b c
    1 2 3 4 5
    [root@VM-24-17-centos shellstudy]# echo ${c}
    3 4 5
    

【例子】

实例程序read.sh

[root@VM-24-17-centos shellstudy]# vim read.sh
#!/bin/bash
read -p 'please input three numbers:' first second third
echo "${first},${second},${third}"
read -n1 -p 'please input y or n:' ans
echo # 换行
echo ${ans}
unset first second third ans
[root@VM-24-17-centos shellstudy]# chmod u+x read.sh 
[root@VM-24-17-centos shellstudy]# ./read.sh 
please input three numbers:1 2 3
1,2,3
please input y or n:y
y

4.2 echo 显示命令

Shell使用echo命令实现标准输出,在屏幕上打印出指定的字符串:

echo [选项] [字符串]
  • -n:不在最后自动换行。
  • -e:启用反斜线控制字符的转换
  • -E:不处理转义字符。此为缺省(默认)选项;

echo命令的转义符(echotest.sh):

转义符含义
\a从系统喇叭发送出声音
\b向左刪除
\c抑制输出后面的字符并且最后不换行
\EESCAPE键
\f换页字符
\n换行字符
\r回车键
\ttab制表符
\反斜线本身

【例子】

[root@VM-24-17-centos shellstudy]# vim echotest.sh
#!/bin/bash
echo -e "this \nis \na \ntest"
echo -E "this \nis \na \ntest"
echo "this \nis \na \ntest"
echo -n "this is a test"
echo ",bye"
echo -e "this is a \ctest"
[root@VM-24-17-centos shellstudy]# chmod u+x echotest.sh 
[root@VM-24-17-centos shellstudy]# ./echotest.sh 
this 
is 
a 
test
this \nis \na \ntest
this \nis \na \ntest
this is a test,bye
this is a 

4.3 数值计算

对数字型变量计算可以使用如下方法:

  1. 用法 1:$((...))

    A=$((3+4))
    
  2. 用法 2:$[..]

    B=$[3+5]
    
  3. 用法3:expr表达式:

    C=`expr 5 + 4` #  注意运算符两侧必须有空格,否则出错
    
  4. 用法4:let指令,计算并赋值:

    let D=5+5
    

【例子】

[root@VM-24-17-centos shellstudy]# vim com.sh
#!/bin/bash
A=$((3+4))
B=$[3+5]
C=`expr 5 + 4`
let D=5+5
echo "${A},${B},${C},${D}"
E=$((3+$((4+$((5+5))))))
echo ${E}
let E++
echo ${E}
unset A B C D E
[root@VM-24-17-centos shellstudy]# chmod u+x com.sh 
[root@VM-24-17-centos shellstudy]# ./com.sh 
7,8,9,10
17
18

4.4 变量表达式测试

​ test命令在Shell脚本程序中主要用于测试一个表达式;如果条件为真,则返回一个0值。如果表达式不为真,则返回一个大于0的值——也可以将其称为假值。其语法如下:

test 表达式

表达式所代表的操作符有字符串操作符、数字操作符、逻辑操作符以及文件操作符。

4.4.1 字符串测试

test表达式含义
str1==str2当str1与str2相同时,返回真
str1!=str2当str1与str2不同时,返回真
str当str不为空字符串时,返回真
-n str当str长度大于0时,返回真
-z str当str长度为0时,返回真

【例子】

[root@VM-24-17-centos shellstudy]# vim strtest.sh
#!/bin/bash
echo -n "Enter your login name: "
read name
if test "${name}" == "root"; # 注意==两边的空格
then    echo "hello,${name},How are you today?"
else    echo "name error,so who are you?"
fi 
[root@VM-24-17-centos shellstudy]# chmod u+x strtest.sh
[root@VM-24-17-centos shellstudy]# ./strtest.sh 
Enter your login name: root
hello,root,How are you today?

上面这种test…形式写起来比较复杂,通常使用下面的方式:

if [ "${name}" = "root" ]; # 同样要注意[]两侧的空格

4.4.2 数值测试

test表达式含义
int1 -eq int2当int1等于int2时,返回真
int1 -ge int2当int1大于/等于int2时,返回真
int1 -le int2当int1小于/等于int2时,返回真
int1 -gt int2当intl大于int2时,返回真
int1 -lt int2当intl小于int2时,返回真
int1 -ne int2当int1不等于int2时,返回真

【例子】

[root@VM-24-17-centos shellstudy]# vim inttest.sh
#!/bin/bash
if [ $# -ne 2 ]; thenecho "not enough parameter"exit 0
fi      
if [ $1 -eq $2 ]; thenecho "$1 equals $2"
elif [ $1 -lt $2 ]; thenecho "$1 littler than $2"
elif [ $1 -gt $2 ]; thenecho "$1 greater than $2"
fi   
[root@VM-24-17-centos shellstudy]# chmod u+x inttest.sh 
[root@VM-24-17-centos shellstudy]# ./inttest.sh
not enough parameter
[root@VM-24-17-centos shellstudy]# ./inttest.sh 2 3
2 littler than 3
[root@VM-24-17-centos shellstudy]# ./inttest.sh 2 2
2 equals 2
[root@VM-24-17-centos shellstudy]# ./inttest.sh 3 2
3 greater than 2

4.4.3 文件测试

test表达式含义
-d file当file是一个目录时,返回真
-f file当file是一个普通文件时,返回真
-r file当file是一个可读文件时,返回真
-w file当file是一个可写文件时,返回真
-x file当file是一个可执行文件时,返回真
-s file当file文件长度大于0时,返回真

【例子】

[root@VM-24-17-centos shellstudy]# vim filetest.sh
#!/bin/bash
echo "please input a file name:"
read file_name
if [ -d $file_name ]; thenecho "${file_name} is a directory"
elif [ -f $file_name ]; thenecho "${file_name} is a common file"
elif [ -c $file_name ];thenecho "${file_name} is a device file"
else    echo "${file_name} is an unknown file"
fi 
[root@VM-24-17-centos shellstudy]# chmod u+x filetest.sh
[root@VM-24-17-centos shellstudy]# ./filetest.sh 
please input a file name:
/etc
/etc is a directory

4.4.4 逻辑测试

test表达式含义
!expr当expr的值是假时,返回真
expr1 -a expr2当expr1和expr2值同为真时,返回真
expr1 -o expr2当exprl和expr2的值至少有一个为真时,返回真

变量测试语句一般不单独使用,一般作为if语句的测试条件,如:

if test -d $1;then...
fi
# 变量测试语句可用[]进行简化,如
test -d $1 等价于 [ -d $1 ] ,切记[]两侧空格

4.5 流程控制语句

​ 和其他高级程序设计语言一样,Shell提 供了用来控制程序和执行流程的命令,包括条件分支和循环结构,用户可以用这些命令创建复 杂的程序。

​ 与传统语言不同的是,Shell用于指定条件值的不是布尔运算式, 而是命令和字符串。

4.5.1 If

if [条件表达式]then语句序列
fi
# 如果你喜欢,也可以将 then 和 if 写在一行:
if  [条件表达式];  then语句序列
fi
# -------------------------------------------------------------------------
if [条件表达式]; then语句序列1
else语句序列2
fi
# -------------------------------------------------------------------------
if [条件表达式1]; then语句序列1
elif [条件表达式2]; then语句序列2
...
else语句序列n
fi

4.5.2 case

case var in表达式1)...;; 表达式2)...;;表达式3)...;;*) # 用通配符*来处理无匹配的情况,相当于其他语言中的default...
esac

【例子】

[root@VM-24-17-centos shellstudy]# vim casetest.sh
#!/bin/bash
echo "*********************************"
echo "please select your operation:" 
echo "press "C" to copy"
echo "press "D" to delete"
echo "press "B" to backup"
echo "*********************************"
read op
case $op inC)echo "your selection is copy" ;;D)echo "your selection is delete" ;;B)echo "yourl selection 1s backup" ;;*)echo "invalide selection"
esac
[root@VM-24-17-centos shellstudy]# chmod u+x casetest.sh 
[root@VM-24-17-centos shellstudy]# ./casetest.sh 
*********************************
please select your operation:
press C to copy
press D to delete
press B to backup
*********************************
C
your selection is copy

5. 补充

  1. 查看登录用户信息:
    1. who am i :当前登录用户,信息较为全面
    2. whoami: 只显示登录用户名
    3. who:较为全面的所有登录用户信息
    4. w:更全面的所有登录用户信息

相关内容

热门资讯

乐鑫科技与Bosch Sens... 12月30日,据“乐鑫董办”消息,乐鑫科技 (688018.SH) 宣布与 Bosch Sensor...
AI时代,腾讯落伍了吗? Meta 宣布收购 Manus ,让“AI 智能体(Agent)”成为了 2025 年末最热的赛道。...
开源证券:爱旭股份技术壁垒深厚... 开源 证券研报指出, 爱旭股份深耕 太阳能电池领域16载,积淀了深厚的技术壁垒。2021年,公司率先...
康恩贝:选举应徐颉任董事长 每经AI快讯,康恩贝(600572)12月30日公告,当日,公司召开第十一届董事会第十四次(临时)会...
德联集团:子公司多品牌售车,多... 投资者提问:据报道贵公司目前收购的汽车公司经营范围有汽车改装,露营,新能源车销售维修之类的业务!贵公...