09. Shell脚本

一、什么是Shell

  Shell 是操作系统中的一个 命令行解释器,主要功能是接收用户命令,然后将这些命令传递给操作系统内核去执行。 Shell 是用户与操作系统内核之间的接口,它允许用户通过命令行或脚本来与操作系统进行交互。同时,Shell 也是一种脚本语言,允许用户编写一系列命令脚本(Shell脚本)以实现自动化任务处理。

  我们可以查看 /etc/shells 文件查看 Linux 提供的 Shell 解释器有哪些。

cat /etc/shells

  然后,我们可以执行 echo $SHELL 命令查看默认使用的是哪个 Shell 解释器。

echo $SHELL

查看Shell解释器和默认使用的解释器

二、一个简易的Shell脚本

  这里,我们使用 vim 新建一个 Shell 脚本。然后,我们在 hello.sh 脚本文件中编写脚本。

#!/bin/bash
echo "Hello world!"

  编写完成之后,我们保存退出该脚本文件。然后,我们可以在终端中通过 sh 命令执行 Shell 脚本。

sh hello.sh

  我们也可以直接运行 hello.sh 脚本文件。

./hello.sh

  当我们直接运行脚本文件时会发现显示权限,这是因为,hello.sh 脚本文件默认没有执行权限。此时,我们可以通过 chmod 命令修改文件权限。

直接运行Shell脚本

三、变量

  在 Shell 编程中,变量是用于存储数据值的名称。我们可以使用 变量名=变量值 的方式 定义变量,然后通过 $变量名 的方式 获取变量的值。在定义变量时,变量名和等号之间不能有空格。如果变量后面不想使用的话,可以使用 unset 变量名 的方式撤销变量。如果我们要 定义只读变量,可以使用 readonly 变量名=变量值 的方式。只读变量不能使用 unset 撤销。如果我们想要变量 提升为全局变量 供给其它 Shell 程序使用,可以使用 export 变量名 的方式。

  同时,变量名的命名须遵循如下规则:

  • 只包含字母、数字和下划线:变量名可以包含字母(大小写敏感)、数字和下划线,不能包含其他特殊字符。
  • 不能以数字开头:变量名不能以数字开头,但可以包含数字。
  • 避免使用 Shell 关键字:不要使用Shell的关键字(例如 if、then、else、fi、for、while 等)作为变量名,以免引起混淆。
  • 避免使用空格:变量名中不应该包含空格,因为空格通常用于分隔命令和参数。

  在 Shell 中,变量值默认都是字符串,如果字符串直接包含空格,则要使用单引号或者双引号括起来。

变量的使用

  我们在使用 Shell 时,Shell 中有几个特殊字符用来处理参数:。

  • $n:在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,0 是 执行的文件名,1 为执行脚本的第一个参数,是传入的第一个参数。2 为执行脚本的第二个参数。如果 n 大于 9,需要使用大括号括起来。
  • $#:传递到脚本的参数个数。
  • $*:以一个单字符串显示所有向脚本传递的参数。
  • $@:与 $* 相同,但是使用时加引号,并在引号中返回每个参数。
  • $?:显示最后命令的退出状态。0 表示没有错误,其它任何值表明有错误。
  • $$:脚本运行的当前进程 ID 号。
  • $-:显示 Shell 使用的当前选项,与 set 命令功能相同。
#!/bin/bash

echo '---------- $n ----------'
echo $0
echo $1
echo $2
echo ${10}

echo '---------- $# ----------'
echo $#

echo '---------- $* ----------'
echo $*

echo '---------- $@ ----------'
echo $@

echo '---------- $? ----------'
echo $?

echo '---------- $$ ----------'
echo $$

echo '---------- $- ----------'
echo $-

特殊字符变量

四、运算符

  在 Shell 中,我们不能直接将运算式赋值给变量,这是因为变量值默认都是字符串。此时我们可以使用 $((运算式))$[运算式] 的方式赋值给变量。

运算式

五、条件判断

  我们可以使用 test 条件表达式[ 条件表达式 ] 进行条件判断。当条件表达式为真时输出 0,否则输出 1。我们还可以判断条件表达式是否为空,其中非空为真,空为假。

  常用的条件判断如下:

  • 两个整数之间的比较
    • -eq等于(equal)。
    • -ne不等于(not equal)。
    • -lt小于(less than)。
    • -le小于等于(less equal)。
    • gt大于(greater than)。
    • -ge大于等于(greater equal)。
  • 按文件权限进行判断
    • -r有读的权限(read)。
    • -w有写的权限(write)。
    • -x有执行的权限(execute)。
  • 按文件类型进行判断
    • -e文件存在(existence)。
    • -f文件存在并且是一个常规文件(file)。
    • -d文件存在并且是一个目录(directory)。

条件判断

  我们还可以进行多条件判断,其中 && 表示 前一条命令执行成功时,才执行后一条命令|| 表示 上一个命令执行失败后,才执行下一条命令

多条件判断

六、流程控制

6.1、分支结构

6.1.1、if分支结构

  我们可以使用 if 语句执行单分支结构。

if [ 条件判断式 ]; then
    程序
fi

  或

if [ 条件判断式 ]
then
    程序
fi

  如果我们要执行多分支逻辑,可以通过以下方式:

if [ 条件判断式 ]
then
    程序
elif [ 条件判断式 ]
then
    程序
else
    程序
fi
#!/bin/bash

if [ $1 -eq 10 ]; then
    echo "num == 10"
elif [ $1 -lt 10 ]
then
    echo "num < 10"
else
    echo "num > 10"
fi

if分支结构

6.1.2、case分支结构

  我们可以使用 case 分支结构判断变量的值是否等于某个值。

case $变量名 in
"值1")
    如果变量的值等于值1,则执行程序1
;;
"值2")
    如果变量的值等于值2,则执行程序2
;;
    ...省略其它分支...
*)
    如果变量的值都不是以上的值,则执行此层序
;;
esac
#!/bin/bash

case $1 in
    "1")
        echo "the first"
        ;;
    "2")
        echo "the second"
        ;;
    "3")
        echo "the third"
        ;;
    *)  
        echo "loser"
        ;;
esac  

casse分支结构

  我们还可以使用 | 合并多个条件。

#!/bin/bash

case $1 in
    "0")
        echo "the number is 0"
        ;;
    "1" | "3" | "5" | "7" | "9")
        echo "this is an odd number less than 10"
        ;;
    "2" | "4" | "6" | "8")
        echo "this is an even number less than 10"
        ;;
    *)
        echo "this is other number"
        ;;
esac 

case合并多个条件

6.2、循环结构

6.2.1、for循环结构

  for 循环的语法格式如下:

for ((初始值;循环控制;迭代控制))
do
    程序
done
#!/bin/bash

sum=0
for ((i = 0; i <= 10; i++)); do
    sum=$[$sum+$i]
done

echo $sum

  然后我们在终端中如下如下命令执行 Shell 脚本:

bash template.sh

  我们还可以使用如下语法遍历值:

for 变量 in 值1 值2 值3 ...
do
    程序
done
#!/bin/bash

for name in sakura mikoto shana
do
    echo "$name is a gril"
done

  $*$@ 都表示传递给函数或脚本的所有参数,不被双引号包含时都以 $1 $2 ... $n 的格式输出所有参数。但是如果用双引号括起来,"$*" 表示一个变量,"$@" 分为多个变量。

#!/bin/bash

echo '---------- $* ----------'
for name in $*
do
    echo "$name is gril"
done

echo '---------- $@ ----------'
for name in $@
do
    echo "$name is gril"
done

echo '---------- "$*" ----------'
for name in "$*"
do
    echo "$name is gril"
done

echo '---------- "$@" ----------'
for name in "$@"
do
    echo "$name is gril"
done

特殊变量的区别

6.2.2、while循环结构

  while 循环结构的语法如下:

while [ 条件表达式 ]
do
    程序
done
#!/bin/bash

i=1
sum=0

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

echo $sum

  然后我们在终端中如下如下命令执行 Shell 脚本:

bash template.sh

七、控制台输入

  我们可以使用 read 命令读取控制台输入

read [选项] 参数

  read 命令可选的选项如下:

  • \p:指定读取值时的提示词。
  • \t:指定读取值等待的时间(单位为秒),如果 -t 不加表示一直等待。
#!/bin/bash

read -t 7 -p "Pleases enter your name within 7 seconds:" name

echo "Hello $name"

控制台输入

八、函数

  在 Shell 中,我们可以自定义函数,它的格式如下:

function 函数名()
{
    函数体;

    return 函数返回值
}

  其中,function 表示是这是一个函数,可以省略。

  Shell 脚本是逐行运行的,因此在调用函数之前,必须先声明函数。Shell 脚本中,函数的返回值只能通过 $? 系统便两个获得,可以显示使用 return 函数返回值函数的返回值只能是 0 到 255 之间的数值,其中 0 表示运行成功,其它值都表示错误)的方式返回。如果不显示的返回,则将以最后一条命令运行结果作为函数返回值。

#!/bin/bash

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

read -p "Please enter the first number:" n1
read -p "Please enter the second number:" n2

sum $n1 $n2

自定义函数

九、Shell工具

9.1、cut工具

  cut 工具用来在文件中剪切数据,cut 命令从文件中每一行剪切字节、字符和字段并将这些字节、字符和字段输出。它的基本用法如下:

cut [选项] 文件名

  其中,它的选项可选值如下:

  • -f 列号:提取第几列。
  • -d 分隔符:分隔符,按照指定分隔符分割列,默认是制表符 \t
  • -c n:按字符进行切割,n 表示取第几列。

cut工具的使用

9.2、awk工具

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

awk [选项] '/匹配模式/{匹配时所要执行的一系列命令}' 文件名

  其中,选项的可选值如下:

  • \F:指定输入文件的分隔符。
  • \v:赋值一个用户定义变量。

  匹配模式 如果省略,则 awk 将对所有行进行操作。匹配时所要执行的一系列命令 如果省略,则默认动作是打印整行。

awk工具的使用

  我们还可以使用 BEGIN{}END{} 在匹配时所要执行的一系列命令添加前置操作和后置操作。

awt工具中使用begin和end

  awk 还内置了一些变量,例如:

  • FILENAME:文件名。
  • NR:以读的记录数(行号)。
  • NF:浏览记录的域的个数(切割后,列的个数)。
awk -F : '{print "filename: " FILENAME ", row:" NR ", col:" NF}' /etc/passwd

awk工具使用系统变量

posted @ 2025-02-04 20:07  星光映梦  阅读(581)  评论(0)    收藏  举报