1 Shell概述

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

Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。

[root@iZlu4gn37663k7Z home]# cat /etc/shells 
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
[root@iZlu4gn37663k7Z bin]# ll |grep bash
-rwxr-xr-x.   1 root root    964608 Oct 31  2018 bash
lrwxrwxrwx.   1 root root        10 Jul 11  2019 bashbug -> bashbug-64
-rwxr-xr-x.   1 root root      6964 Oct 31  2018 bashbug-64
lrwxrwxrwx.   1 root root         4 Jul 11  2019 sh -> bash

由上可知bash与sh一样,只是个软连接罢了

2 Shell脚本入门

  • 脚本格式

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

  • 第一个 Shell 脚本:helloworld

    需求:创建一个 Shell 脚本,输出 helloworld

    #!/bin/bash 
    echo "helloworld"
  • 脚本的常用执行方式

    第一种:采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)

    sh+脚本的相对路径

    sh helloworld.sh

    sh+脚本的绝对路径

    sh /home/atguigu/datas/helloworld.sh

    bash+脚本的相对路径

     bash helloworld.sh

    bash+脚本的绝对路径

    bash /home/atguigu/datas/helloworld.sh

    第二种:采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)

    首先要赋予 helloworld.sh 脚本的+x 权限

    chmod +x helloworld.sh

    执行脚本

    # 相对路径
    ./helloworld.sh
    # 绝对路径
    /home/atguigu/datas/helloworld.sh
  • 注意:第一种执行方法,本质是 bash 解析器帮你执行脚本,所以脚本本身不需要执行权限。

    ​ 第二种执行方法,本质是脚本需要自己执行,所以需要执行权限。

3 变量

3.1 系统预定义变量

  • 常用系统变量

    \$HOME、\$PWD、\$SHELL、\$USER

  • 查看系统变量的值

    echo $HOME

  • 显示当前 Shell 中所有变量

    set

3.2 自定义变量

  1. 基本语法

    1. 定义变量:变量=值;变量=‘值’;变量=“值”(双引号括的东西可以被识别,单引号则是死的、固定的字符串,类似于pyhon的 f'字符串里直接输出{变量}',亦或是 '字符串里直接输出{}'.formath(变量) )
    2. 撤销变量:unset变量
    3. 声明静态变量:readonly变量,注意:不能unset
  2. 变量定义规则

    1. 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写
    2. 等号两侧不能有空格
    3. 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
    4. 变量的值如果有空格,需要使用双引号或单引号括起来。
  3. 注意事项

    1. readonly声明的静态变量,不能 unset
    2. 在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算
    3. export加变量名可把变量提升为全局环境变量,可供其他 Shell 程序使用

3.3 特殊变量

3.3.1 \$n

1 基本语法

​ \$n (功能描述:n为数字,\$0代表该脚本名称,\$1-\$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如\${10})

2 案例操作

[root@iZlu4gn37663k7Z datas]$ vim parameter.sh

#!/bin/bash
echo "$0 $1 $

[root@iZlu4gn37663k7Z datas]$ chmod 777 parameter.sh
[root@iZlu4gn37663k7Z datas]$ ./parameter.sh cls xz
./parameter.sh cls xz

3.3.2 \$\

1 基本语法

​ \$#(功能描述:获取所有输入参数个数,常用于循环)。

2 案例实操

[root@iZlu4gn37663k7Z datas]$ 

#!/bin/bash
echo "$0 $1 $2"
echo $#

[root@iZlu4gn37663k7Z datas]$ chmod 
parameter.sh cls xz
2

3.3.3 \$*、\$@

1 基本语法

​ \$\*(功能描述:这个变量代表命令行中所有的参数,\$*把所有的参数看成一个整体)

​ \$@(功能描述:这个变量也代表命令行中所有的参数,不过\$@把每个参数区分对待)

​ 注意:如果想让\$\*和\$@ 体现区别必须用双引号括起来才生效,下文 for 循环中可以显示出区别

2 案例实操

[root@iZlu4gn37663k7Z datas]$ vim

#!/bin/bash
echo "$0 $1 $2"
echo $#
echo $*
echo $@

[root@iZlu4gn37663k7Z datas]$ bash parameter.sh 1 2 3
parameter.sh 1 2
3
1 2 3
1 2 3

3.3.4 \$?

1 基本语法

​ \$?(功能描述:最后一次执行的命令的返回状态。如果这个变量的值为 0,证明上一个命令正确执行;如果这个变量的值为非 0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。0->True; !0->False

2 案例实操

[root@iZlu4gn37663k7Z datas]$ ./helloworld.sh
hello world
[root@iZlu4gn37663k7Z datas]$ echo $?
0

4 运算符

1 基本语法

​ “\$((运算式))”或“\$[运算式]”

算术运算符 说明/含义
+、- 加法(或正号)、减法(或负号)
*、/、% 乘法、除法、取余(取模)
** 幂运算
++、-- 自增和自减,可以放在变量的前面也可以放在变量的后面
!、&&、|| 逻辑非(取反)、逻辑与(and)、逻辑或(or)
<、<=、>、>= 比较符号(小于、小于等于、大于、大于等于)
==、!=、= 比较符号(相等、不相等;对于字符串,= 也可以表示相当于)
<<、>> 向左移位、向右移位
~、|、 &、^ 按位取反、按位或、按位与、按位异或
=、+=、-=、*=、/=、%= 赋值运算符,例如 a+=1 相当于 a=a+1,a-=1 相当于 a=a-1

2 案例实操

​ 计算(2+3)X4 的值

[root@iZlu4gn37663k7Z datas]# S=$[(2+3)*4]
[root@iZlu4gn37663k7Z datas]# echo $S

5 条件判断

1 基本语法

  • test confition

  • [condition](注意condition前后要有空格)

    注意:条件非空即为true,[aaa]返回true,[]返回false。

2 常用判断条件

  • 字符串比较
    • $str1 = $str2 : 相等比较
    • $str1 != $str2 : 不等比较
    • $str1 \\< $str2 : str1小于str2为true,比较字母在字母表顺序,字母越靠后就越大,反之越小
    • $str1 \\> $str2 : str1大于str2为true,比较字母在字母表顺序,字母越靠后就越大,反之越小
    • -n $str1 : str1长度不是0则为true
    • -z $str1 : str1长度为0则为true,-z 是Zero简写

注:字符串比较大小,首先会将首个字符转化成ASCII码进行比较大小,如果相同会继续比较第二个字符以此类推,但是需要注意如果是数字类型的字符串如"12",进行比较会出问题,比较数字大小还是使用-gt、-lt等,大小号慎用。

在shell中 > 或 < 是输入或输出重定向符号,需要加反斜杠作转义

两个字符串比较时,比较符两边要有空格

  • 两个整数之间比较
    • -lt 小于(less than)
    • -le 小于等于(less equal)
    • -eq 等于(equal)
    • -gt 大于(greater than)
    • -ge 大于等于(greater equal)
    • -ne 不等于(Not equal)
  • 或且非
    • -o : 或。用法:[ $value == "stop" -o $value == "restart" ]
    • -a : 且。用法:[ $value == "stop" -a $value == "restart" ]
    • || : 或。用法:[ $value == "stop" ] || [ $value == "restart" ]
    • &&:且。用法:[ $value == "stop" ] && [ $value == "restart" ]
    • ! : 非。用法:[ $value != "stop" ]
  • 按照文件权限进行判断
    • -r 有读的权限(read)
    • -w 有写的权限(wr
    • -x 有执行的权限(execute)
  • 按照文件类型进行判断
    • -f 文件存在并且是一个常规的文件(file)
    • -e 文件存在(existence)
    • -d 文件存在并是一个目录(directory)

3 案例实操

# 23 是否大于等于 22
[root@iZlu4gn37663k7Z datas]$ test 23 -ge 22
[root@iZlu4gn37663k7Z datas]$ echo $?
0
[root@iZlu4gn37663k7Z datas]$ [ 23 -ge 22 ]
[root@iZlu4gn37663k7Z datas]$ echo $?
0

# helloworld.sh 是否具有写权限
[root@iZlu4gn37663k7Z datas]$ test -w helloworld.sh
[root@iZlu4gn37663k7Z datas]$ echo $?
0
[root@iZlu4gn37663k7Z datas]$ [ -w helloworld.sh ]
[root@iZlu4gn37663k7Z datas]$ echo $?
0

# /home/atguigu/cls.txt 目录中的文件是否存在
[root@iZlu4gn37663k7Z datas]$ test -e /home/atguigu/cls.txt
[root@iZlu4gn37663k7Z datas]$ echo $?
1
[root@iZlu4gn37663k7Z datas]$ [ -e /home/atguigu/cls.txt ]
[root@iZlu4gn37663k7Z datas]$ echo $?
1

# 多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失败后,才执行下一条命令)
[root@iZlu4gn37663k7Z ~]$ [ condition ] && echo OK || echo notok
OK
[root@iZlu4gn37663k7Z datas]$ [ condition ] && [ ] || echo notok
notok

6 流程控制

6.1 if 判断

1 基本语法

# 无分支if
if [ 条件判断式 ]
then
    程序块
fi # 结束,类似于end

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

2 注意事项

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

3 案例实操

# !/bin/bash

if [ $1 -eq "1" ]
then
    echo "输入的是1"
elif [ $1 -eq "2" ]
then
    echo "输入的是2"
else
    echo "超出理解范围"
fi

6.2 case 语句

1 基本语法

case $变量名 in
"值1")
    若变量值等于值1,则执行该程序块
;;
"值2")
    若变量值等于值2,则执行该程序块
;;
*)
    若变量值都不是以上值,则执行该程序块
;;
esac # 结束,类似于end

2 注意事项:

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

3 案例实操

# !/bin/bash

case $1 in
"1")
    echo "输入的是一"
;;
"2")
    echo "输入的是二"
;;
*)
    echo "超出理解范围"
;;
esac

6.3 for 循环

1 基本语法1

for (( 初始值;循环控制条件;变量变化 ))
do
    程序
done

2 案例实操

# !/bin/bash
# 从1加到100
s=0 # 不能有空格(不能写成s = 0)

for (( i=0; i<=100; i++ ))
do
        s=$[$s+$i]
done

echo $s

1 基本语法2

for 变量 in 值1 值2 值3...
do
    程序
done

2 案例实操

# !/bin/bash
# 打印所有参数"$*"

for i in $*
do
    echo "这是参数$i"
done

[root@iZlu4gn37663k7Z shell_learn]# sh for2.sh as fds gdf hg dsf
这是参数as
这是参数fds
这是参数gdf
这是参数hg
这是参数dsf
# !/bin/bash
# 查看 $* 和 $@ 的区别

echo "=======================带双引号==========================="

echo '$*:'
for i in "$*"
#$*中的所有参数看成是一个整体,所以这个 for 循环只会循环一次 
do
        echo "$i" 
done

echo '$@:'
for j in "$@"
#$@中的每个参数都看成是独立的,所以“$@”中有几个参数,就会循环几次 
do
        echo "$j" 
done

echo "======================不带双引号=========================="

echo '$*:'
for i in $*
do
        echo "$i" 
done

echo '$@:'
for j in $@
do
        echo "$j" 
done

[root@iZlu4gn37663k7Z shell_learn]# sh for3.sh a b c d e
=======================带双引号===========================
$*:
a b c d e
$@:
a
b
c
d
e
======================不带双引号==========================
$*:
a
b
c
d
e
$@:
a
b
c
d
e

此时可回顾本文3.3.3。

6.4 while 循环

1 基本语法

while [ 条件判断式 ]
do
    程序
done

2 案例实操

# !/bin/bash
# 从1加到100

s=0
i=1
while [ $i -le 100 ]
do
    s=$[$s+$i]
    i=$[$i+1]
done

echo $s

7 read 读取控制台输入

1 基本语法

read(选项)(参数)
# 选项:
# -p:指定读取值时的提示符
# -t:指定读取值时等待的时间
# 参数:
# 变量:指定读取值时的变量名

2 案例实操

# !/bin/bash
# 10s内输入(-t的作用),并且提示输入y/n(-p的作用),将用户输入内容赋给 INPUT 这个变量

read -t 10 -p "Whether to install this software <y/n>?" INPUT

while [ $INPUT != 'y' ] && [ $INPUT != 'n' ]
do
        read -t 10 -p ".............................>" INPUT
done

if [ $INPUT == 'y' ]
then
        echo "Installing, please wait..."
elif [ $INPUT == 'n' ]
then
        echo "Bye"
fi
[root@iZlu4gn37663k7Z shell_learn]# sh read.sh 
Whether to install this software <y/n>?y
Installing, please wait...

[root@iZlu4gn37663k7Z shell_learn]# sh read.sh 
Whether to install this software <y/n>?n
Bye

[root@iZlu4gn37663k7Z shell_learn]# sh read.sh 
Whether to install this software <y/n>?dsf
.............................>fhf
.............................>c
.............................>dtr
.............................>bfd
.............................>n
Bye

[root@iZlu4gn37663k7Z shell_learn]# sh read.sh 
Whether to install this software <y/n>?sdf
.............................>fh
.............................>y
Installing, please wait...

8 函数

8.1 系统函数

8.1.1 basename

1 基本语法

basename [string / pathname] [suffix]

(功能描述:basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。

2 参数解释

string / pathname:一段字符串或某个路径。

suffix 为后缀,如果 suffix 被指定了,basename 会将 pathname 或 string 中的 suffix 去掉。

3 案例实操

# 截取该/home/admin/test.txt 路径的文件名称
[atguigu@hadoop101 datas]$ basename /home/admin/test.txt 
test.txt 
[atguigu@hadoop101 datas]$ basename /home/admin/test.txt .txt 
test

8.1.2 dirname

1 基本语法

dirname 文件绝对路径

(功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录的部分),然后返回剩下的路径(目录的部分))

2 案例实操

# 获取 test.txt 文件的路径
[atguigu@hadoop101 ~]$ dirname /home/admin/banzhang.txt 
/home/admin

8.2 自定义函数

1 基本语法

# 定义函数
[ function ] funname[()]
{
    Action;
    [return int;]
}

# 调用函数
funname

2 经验技巧

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

3 案例实操

# !/bin/bash
# 两数之和

function sum()
{
    s=0
    s=$[$1+$2]
    echo "$s"
}

read -p "Please input the number1: " n1; 
read -p "Please input the number2: " n2; 
sum $n1 $n2;
[root@iZlu4gn37663k7Z shell_learn]# sh sum.sh
Please input the number1: 1
Please input the number2: 2
3

9 Shell 工具

9.1 cut

cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

1 基本用法

cut [ 选项参数 ] filename

说明:默认分隔符是制表符

2 选项参数说明

选项参数 功能
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列
-c 指定具体的字符

3 案例实操

[root@iZlu4gn37663k7Z shell_learn]# vim cut.txt
wo ta 
jiao shi
ba an
nie na
bo ka
he lie
fu ni
o na

[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1 cut.txt 
wo
jiao
ba
nie
bo
he
fu
o

[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1,2 cut.txt 
wo ta
jiao shi
ba an
nie na
bo ka
he lie
fu ni
o na

[root@iZlu4gn37663k7Z shell_learn]# cut -d ' ' -f 1 cut.txt | grep nie | cut -d ' ' -f 1 
nie

[root@iZlu4gn37663k7Z shell_learn]# cut -c 1 cut.txt 
w
j
b
n
b
h
f
o

9.2 awk

一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

1 基本语法

awk [ 选项参数 ] ‘pattern1{action1} pattern2{action2}...’ filename

pattern:表示 AWK 在数据中查找的内容,就是匹配模式

action:在找到匹配内容时所执行的一系列命令

2 选项参数说明

选项参数 功能
-F 指定输入文件折分隔符
-v 赋值一个用户定义变量

3 案例实操

9.3 sort

sort 命令是在 Linux 里非常有用,它将文件进行排序,并将排序结果标准输出。

1 基本语法

sort(选项)(参数)

选项 说明
-n 依照数值的大小排序
-r 以相反的顺序来排序
-t 设置排序时所用的分隔字符
-k 指定需要排序的列

参数:指定待排序的文件列表

2 案例实操

# 数据准备
[atguigu@hadoop102 datas]$ touch sort.sh 
[atguigu@hadoop102 datas]$ vim sort.sh 
bb:40:5.4 
bd:20:4.2 
xz:50:2.3 
cls:10:3.5 
ss:30:1.6

# 按照“:”分割后的第三列倒序排序。
[atguigu@hadoop102 datas]$ sort -t : -nrk 3 sort.sh
bb:40:5.4 
bd:20:4.2 
cls:10:3.5 
xz:50:2.3 
ss:30:1.6
最后修改:2022 年 08 月 22 日
如果觉得我的文章对你有用,请随意赞赏