Linux运维--Shell基础

Shell概述

Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核。

image-20240810211158626

1
2
3
4
5
6
7
8
9
10
11
# 查看 Shell 解释器
[cc@CentOSByCC ~]$ cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
# Centos 默认的解析器是 bash
[cc@CentOSByCC ~]$ echo $SHELL
/bin/bash

脚本编写入门

规范

脚本以 #!/bin/bash 开头(指定解析器)

1
2
#!/bin/bash
echo "helloworld!"

执行方式

Shell文件后缀名为 .sh,在终端中的执行方式有多种:

  • bash 文件路径

  • sh 文件路径

  • . 文件路径

  • source 文件路径

  • 文件路径(需要先 赋予 Shell 文件的 +x 权限)

    1
    2
    3
    [cc@CentOSByCC 桌面]$ chmod +x helloworld.sh 
    [cc@CentOSByCC 桌面]$ ./helloworld.sh
    helloword!

区别:

bash 与 sh 执行为一个独立的环境(打开一个子shell来执行脚本内容,当脚本内容结束,则
子 shell 关闭,回到父 shell 中),. 和 source 为脚本执行环境。

开子 shell 与不开子 shell 的区别就在于,环境变量的继承关系,如在子 shell 中设置的
当前变量,父 shell 是不可见的。

输入与输出

  • echo:回响(输出);

  • read:读取信息(输入);

    read 选项:

    • -p:指定读取值时的提示符;
    • -t:指定读取值时等待的时间(秒)如果-t 不加表示一直等待
    1
    2
    read -p "请输入你的姓名:" name;
    echo "你好,$name";

变量

系统预定义变量

1
2
3
4
5
6
7
8
9
10
# 常用系统变量有 $HOME$PWD$SHELL$USER
# 查看系统变量的值
[cc@CentOSByCC ~]$ echo $SHELL
/bin/bash
[cc@CentOSByCC ~]$ echo $USER
cc
# 显示当前 Shell 中所有的变量
[cc@CentOSByCC ~]$ set
# 显示当前 Shell 中所有的全局变量
[cc@CentOSByCC ~]$ env

自定义变量

基本语法

  • 定义变量:变量名=变量值 ( = 号前后不能有空格)

  • 撤销变量: unset 变量名

  • 声明静态变量: readonly 变量名 (只读,不能修改、撤销)

  • 声明全局变量:export 变量名 (提供给子 shell 使用)

变量定义规则

  • 变量名可以由字母,数字和下划线组成,但是不能以数组开头,环境变量名建议大写

  • 等号左右两侧不能有空格

  • 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算

  • 变量的值如果有空格,必须用双引号或者单引号括起来

特殊变量

$n

1
2
3
4
5
6
7
8
9
10
11
# n 为数字,$0 代表该脚本名称,$1-$9 代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}

[cc@CentOSByCC 桌面]$ vim test.sh
#!/bin/bash
echo $0
echo $1
echo $2
[cc@CentOSByCC 桌面]$ bash test.sh 1 2
test.sh
1
2

$#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 获取所有输入参数个数,常用于循环,判断参数的个数是否正确

[cc@CentOSByCC 桌面]$ vim test.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo "---------"
echo $#
[cc@CentOSByCC 桌面]$ bash test.sh 1 2
test.sh
1
2
---------
2

$*

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# $* 代表命令行中所有的参数,$* 把所有的参数看成一个整体
# $@ 也代表命令行中所有的参数,不过$@把每个参数区分对待

[cc@CentOSByCC 桌面]$ vim test.sh
#!/bin/bash
echo $0
echo $1
echo $2
echo "---------"
echo $#
echo $@
[cc@CentOSByCC 桌面]$ bash test.sh 1 2 3 4 5
test.sh
1
2
---------
1 2 3 4 5
1 2 3 4 5

区别:

$* 可用于查看参数

$@ 可看作参数的一个数组集合,可用于遍历参数

$?

1
2
3
4
5
6
# 最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了

[cc@CentOSByCC 桌面]$ bash helloworld.sh
helloword!
[cc@CentOSByCC 桌面]$ echo $?
0

$$ 代表当前程序的 PID

运算符

整数运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# expr (乘法运算需要转译 \* )
[cc@CentOSByCC 桌面]$ expr 4 / 2
2
[cc@CentOSByCC 桌面]$ expr 4 \* 2
8

# $(())
[cc@CentOSByCC 桌面]$ a=$((5*2))
[cc@CentOSByCC 桌面]$ echo $a
10

# $[]
[cc@CentOSByCC 桌面]$ b=$[6-3]
[cc@CentOSByCC 桌面]$ echo $b
3

# let
[cc@CentOSByCC 桌面]$ let sum=2*3
[cc@CentOSByCC 桌面]$ echo $sum
6

小数运算

1
2
3
4
5
# 安装计算器程序bc
yum install -y bc
# 基本使用
echo "1+2" | bc
echo "scale=2;10/3" | bc # scale=2 表示保留小数点后两位

条件判断

1
2
3
4
5
6
7
8
9
10
11
# 基本语法
test condition
[ condition ] # 注意 condition 前后要有空格

# 条件非空为 true ,即空返回 false
[cc@CentOSByCC 桌面]$ [ shell ]
[cc@CentOSByCC 桌面]$ echo $?
0
[cc@CentOSByCC 桌面]$ [ ]
[cc@CentOSByCC 桌面]$ echo $?
1

整数比较

判断符 描述
-eq 等于(equal)
-ne 不等于(not equal)
-lt 小于(less than)
-le 小于等于(less equal)
-gt 大于(greater than)
-ge 大于等于(greater equal)

字符串判断

判断符 描述
= 相等
!= 不等
-z 长度为0
-n 长度不为0

查看字符串变量长度

1
${#变量名} 

文件权限判断

判断符 描述
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执行的权限(execute)

文件类型判断

判断符 描述
-e 文件存在(existence)
-f 文件存在并且是一个常规的文件(file)
-d 文件存在并且是一个目录(directory)

多条件判断

语法:[ 条件1 判断符 条件2 ]

判断符 描述
-a 两个条件都成立时为真
-o 其中一个成立就为真

&& 表示前一条命令执行成功时,才执行后一条命令

|| 表示上一条命令执行失败后,才执行下一条命令

1
2
3
4
5
6
7
8
9
10
11
# 判断 30 是否大于 25
[cc@CentOSByCC 桌面]$ [ 30 -ge 25 ]
[cc@CentOSByCC 桌面]$ echo $?
0
# 判断 helloworld.sh 是否具有写权限
[cc@CentOSByCC 桌面]$ [ -w helloworld.sh ]
[cc@CentOSByCC 桌面]$ echo $?
0
# 多条件判断
[cc@CentOSByCC 桌面]$ [ atguigu ] && echo OK || echo notOK
OK

流程控制

if判断

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
# 单分支(1)
if [ 条件判断式 ];then
程序
fi
# 单分支(2)
if [ 条件判断式 ]
then
程序
fi

# 双分支
if [ 条件判断式 ];then
程序
else
程序
fi

# 多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi

注意事项:

  • [ 条件判断式 ] 中括号和条件判断式之间必须有空格
  • if 后要有空格

case语句

1
2
3
4
5
6
7
8
9
10
11
12
13
# 基本语法
case $变量名 in
"值 1")
如果变量的值等于值 1,则执行程序 1
;;
"值 2")
如果变量的值等于值 2,则执行程序 2
;;
…省略其他分支…
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac

注意事项:

  • case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束
  • 双分号“;;”表示命令序列结束,相当于 java 中的 break
  • 最后的“*)”表示默认模式,相当于 java 中的 default

for循环

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
31
32
33
34
# 基本语法1
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done

# 计算 1 加到 100
#!/bin/bash
sum=0
for ((i=0;i<=100;i++))
do
sum=$[$sum+$i]
done
echo $sum

# 基本语法2
for 变量 in 值 1 值 2 值 3…
do
程序
done

# 打印参数
#!/bin/bash
for i in 1 2 3 4 5
do
echo "现在打印的是" $i
done

[cc@CentOSByCC 桌面]$ bash for2.sh
现在打印的是 1
现在打印的是 2
现在打印的是 3
现在打印的是 4
现在打印的是 5

{1..10}、$(seq 1 10)、seq 10 都可以表示1到10

while循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 基本语法
while [ 条件判断式 ]
do
程序
done

# 计算 1 加到 100
#!/bin/bash
sum=0
i=1
while [ $i -le 100 ]
do
sum=$[$sum+$i]
i=$[$i+1]
done
echo $sum

调试脚本:

在执行脚本时加上参数,比如:bash -n test.sh

  • -n:仅调试脚本中的语法错误
  • -vx:以调试的方式执行,查询整个执行过程

函数

系统函数

语法 描述
basename 取文件路径里的文件名称
dirname 取路径里的绝对路径名称
1
2
3
4
5
6
7
8
9
10
11
12
# basename [string / pathname] [suffix]
# basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
# suffix 为文件后缀,如果指定,则只显示不带后缀的文件名
[cc@CentOSByCC 桌面]$ basename test1/test.txt
test.txt
[cc@CentOSByCC 桌面]$ basename test1/test.txt .txt
test

# dirname 文件绝对路径
# 从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分)
[cc@CentOSByCC 桌面]$ dirname test1/test.txt
test1

自定义函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 基本语法
[ function ] funname[()]
{
Action;
[return int;]
}

# 计算两输入参数之和
#!/bin/bash
function sum()
{
sum=$[$1+$2]
echo $sum
}
read -p "Please input the number1: " n1;
read -p "Please input the number2: " n2;
sum $n1 $n2
[cc@CentOSByCC 桌面]$ bash fun.sh
Please input the number1: 2
Please input the number2: 3
5

(1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一样先编译。
(2)函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return 后跟数值 n(0-255)。

正则表达式

正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

常规匹配

1
2
# 匹配所有包含 root 的行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep root

特殊字符匹配

特殊字符 描述
^ 匹配一行的开头
$ 匹配一行的结束
. 匹配一个任意的字符
* 表示匹配上一个字符 0 次或多次
[] 表示匹配某个范围内的一个字符
\ 将转义字符和特殊字符连用,来表示特殊字符本身
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 匹配出所有以 a 开头的行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep ^a
# 匹配出所有以 b 结尾的行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep b$
# 匹配包含 ayub,auib,aiob,ajib等的所有行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep a..b
# 匹配包含 ac,abc,abbc,abbbc等的所有行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep ab*c

[6,8] # 匹配 6 或 8
[0-9] # 匹配一个 0-9 的数字
[0-9]* # 匹配任意长度的数字字符串
[a-z] # 匹配一个 a-z 之间的字符
[a-z]* # 匹配任意长度的字母字符串
[a-c, e-f] # 匹配 a-c 或者 e-f 之间的任意字符
# 匹配 rt,rat, rbt, rabt, rbact,rabccbaaacbt 等所有行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep r[a,b,c]*t

# 会匹配所有包含 a$b 的行
[cc@CentOSByCC 桌面]$ cat /etc/passwd | grep ‘a\$b’

文本处理工具

cut

从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

1
2
# 基本语法
cut [选项参数] filename
选项参数 功能
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列,默认是制表符“\t”
-c 按字符进行切割 后加加 n 表示取第几列 比如 -c 1

awk