Shell快速入门笔记

news2024/12/25 0:00:13

文章目录

  • Shell 快速入门笔记
    • 1、Shell概述
    • 2、Shell初体验
    • 4、注释
    • 5、变量
    • 6、数据类型
      • 6.1 字符串
      • 6.2 数组
    • 7、参数传递
    • 8、运算符
    • 9、常用命令
      • 9.1 echo命令
      • 9.2 printf命令
      • 9.3 test命令
    • 10、流程控制
      • 10.1 条件判断
      • 10.2 循环
    • 11、函数
    • 12、输入/输出重定向
      • 12.0 前置知识
      • 12.1 输出重定向
      • 12.2 输入重定向
    • 13、文件包含

Shell 快速入门笔记

1、Shell概述

  • Shell是什么

    在Linux中,Shell是一种命令行界面(CLI),用于与操作系统交互和运行各种命令和程序。Linux操作系统支持多种不同的Shell,每种Shell都有自己的特点和功能。

    个人理解:在Linux中,Shell是一种C语言编写的程序,类似于其它编程语言,它是解释执行的,是连接用户和操作系统的桥梁

  • Shell在计算机中所处的位置

  • Shell能干什么

    Shell是一种脚本语言,所以一般讨论Shell的作用,都是说Shell编写的程序,即Shell脚本的作用

    • 自动化任务:Shell脚本可以用于执行一系列操作和命令,从而自动化一些任务。例如,你可以编写一个Shell脚本来备份你的文件系统,定时运行这个脚本,以确保你的数据得到保护。
    • 批量处理数据:Shell脚本可以用于处理大量的数据。例如,你可以编写一个Shell脚本来查找一个文件夹中所有的文本文件,并将它们转换为另一种格式。
    • 系统管理:Shell脚本可以用于管理系统的各个方面,例如安装软件包、创建用户和设置权限等。
    • 任务调度:Shell脚本可以用于创建和管理计划任务,例如定期执行系统备份或日志清理等。
    • 监控和管理进程:Shell脚本可以用于监控和管理进程,例如启动、停止或重启进程,或者检查进程是否在运行等。
  • Linux中Shell有哪些

    • Bourne Shell(/bin/sh):最早的Unix shell,由Stephen Bourne开发,也称为sh。它是现代Unix shell的基础,可以在几乎所有的Unix和Linux系统上找到。
    • C Shell(/bin/csh):由Bill Joy开发,也称为csh。它是一种基于C语言的shell,具有交互式命令行编辑和命令历史记录等特性。在许多Linux系统中,可以通过安装csh软件包来使用它。
    • Korn Shell(/bin/ksh):由David Korn开发,也称为ksh。它是Bourne Shell的扩展,提供了更多的功能和命令,如命令行编辑、作业控制、数组等。它在Solaris和AIX等Unix系统中广泛使用。
    • Bourne-Again Shell(/bin/bash):由Brian Fox和Chet Ramey开发,也称为bash。它是Bourne Shell的扩展,添加了许多新特性,如命令行编辑、自动补全、历史命令等。它是Linux系统默认的shell。
    • Z Shell(/bin/zsh):由Paul Falstad开发,也称为zsh。它是一种功能强大的shell,具有高级的命令行编辑和自动补全、路径展开等特性。它通常在Mac OS X和一些Linux系统中使用。

    除了上述这些主要的shell,还有其他一些不太常用的shell,如fish(Friendly Interactive Shell)、rc shell、es shell等

  • Shell脚本是什么

    Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

    备注:业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。

2、Shell初体验

按照惯例😄,我们在学习一门新的语言时,都先学会如何打印"Hello World!",现在就让我们来学习如何使用Shell打印一个”Hello World!“吧(●’◡’●)

  • Shell脚本运行所需要的东西shell编辑器+shell解释器

    shell编辑器一般用的是vi\vim,shell解释器一般用的是bash解释器

  • 运行一个Shell脚本的主要步骤

    • Step1编写Shell

      1)创建一个新的文本文件,通常使用.sh作为文件扩展名

      # 在当前目录创建一个名为 hello.sh的文件
      vim hello.sh
      

      2)编码

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

      第一行:指定一个Shell解释器,这里使用的是bash解释器

      第二行:使用Shell提供的指令,编写一个Shell程序

      3)保存退出:按下ESC,从输入模式进入命令模式,然后按下:进入编辑模式,然后输入wq回车

    • Step2运行Shell,运行Shell脚本的方式有很多种,这里演示一些常见的方式

      前面我们shell脚本的路径是:/home/ghp/hello.sh

      • 方式一绝对路径/相对路径

        绝对路径:

        chmod +x hello.sh
        ./home/ghp/hello.sh
        

        相对路径:

        chmod +x hello.sh
        ./hello.sh
        

        备注:新建的文件默认是没有执行(x)权限的,需要赋值

      • 方式二sh/bash

        # sh方式
        sh hello.sh
        # bash方式
        bash hello.sh
        

        这种方式的特点:使用这种方式不需要给文件设置执行权限,但是会导致shell脚本可能不是由我们指定的shell解释器执行,

        比如,我们使用 #!指定的是 bash 解释器,但是我们使用 sh hello.sh运行,此时执行该脚本的shell解释器就不是我们指定的 bash 解释器,而变成了 sh 解释器。所以使用这种方式,在编写Shell脚本时可以直接不指定 shell 解释器

        sh和bash的区别和联系/bin/sh是早期版本,是一种便携方式的解释性脚本语言,自带有posix便携式功能,以该方式声明的脚本,脚本中间发生错误会终止脚本的运行,不再运行下面的代码/bin/bash,是/bin/sh的升级版,默认没有开启posix便携模式,所以以 /bin/bash 声明的脚本,中间即使发生错误,依然会继续向下运行

        可以简单的理解:/bin/sh 等价于 /bin/bash --posix

        注意:现在Linux(2.6.18)中,sh已经被bash整合了,我们使用的 sh 其实是 bash 的软链接,sh 就是 bash --posix,可以使用man shman bash 测试当前系统 sh 是否已经被bash整合了

      • 方式三./source

        # . 方式
        . hello.sh
        # source 方式
        source hello.sh
        

        备注:需要给文件赋予执行(x)权限。./source 都是继承 /bin/bash 的权限,和 bash 方式不同的是,它不会开启一个子shell线程,而是直接在当前shell进程下执行的,因为他们是内建命令,所以脚本中赋值的本地变量也会影响当前shell的,用的时候一定要注意(尽量使用前面的3种方式),一般方式三都是用于执行配置文件

      总结

      1. 方式一需要Shell脚本有可执行权限,方式二和方式三不需要
      2. 方式一和方式二在脚本执行时,会开启一个子shell环境,在子shell执行完成后,子shell环境随即关闭,然后又回到当前shell中;而方式三不会开启子shell,而是直接在当前shell线程中进行执行脚本

4、注释

  • 注释的定义:注释是在Shell脚本中用来标识代码的解释或说明的一种特殊文本。在执行Shell脚本时,注释会被忽略,不会对程序的执行造成任何影响。

    注意:shell脚本的第一行的#!注释是有作用的,它指定了使用哪一个shell解释器去执行这个脚本(但如何使用bash/sh去执行脚本就不一定就是这个解释器去执行)

  • 注释的作用

    • 提高代码的可读性和可维护性。通过注释,程序员可以更加清晰地了解代码的意图和实现方法,从而更方便地进行代码的修改和调试。
    • 方便代码的协作和共享。注释可以帮助其他程序员更好地理解和使用自己的代码,减少因为代码不明确而导致的沟通障碍和误解。
  • 注释的分类

    • 行注释(Line Comments):行注释是在一行代码的末尾加上一段注释,通常使用“#”符号来表示。行注释只对当前行有效,不会影响后续代码的执行。
    • 块注释(Block Comments):块注释是在多行代码中间加上一段注释,通常使用“:<<”和“:”符号来表示。块注释可以跨越多行,但必须以“:”符号结束。
    • 文档注释(Document Comments):文档注释是用来描述代码整体的一种注释,通常放置在代码的开头。文档注释可以使用特定的标记和格式,如“/**”和“*/”符号,以方便生成文档或注释。

    示例:

    行注释:
    # 注释内容
    
    块注释(下面的EOF可以替换称其它字符,比如END、!、?...)
    :<<EOF
    注释内容
    注释内容
    注释内容
    EOF
    
    文档注释:
    #!/bin/bash
    #
    # Script name: backup.sh
    #
    # Description:
    # This script is used to backup files from a source directory to a destination directory.
    #
    # Usage:
    # ./backup.sh <source directory> <destination directory>
    #
    # Options:
    # -v : verbose output
    #
    # Return values:
    # 0 : success
    # 1 : error
    #
    # Examples:
    # ./backup.sh /home/user /mnt/backup
    # ./backup.sh -v /home/user /mnt/backup
    #
    
    # Script code goes here...
    
  • 注释应当遵循以下规范

    • 注释应该简洁明了,不要过度注释,也不要遗漏重要的注释信息。注释应该突出代码中最重要、最难理解、最易出错的部分,对这些部分进行详细的解释和说明。
    • 注释应该使用简单、易懂的语言,避免使用专业术语和难懂的缩写。注释应该能够被任何人理解,包括不具备编程背景的人。
    • 注释应该与代码保持一致,注释应该与代码在格式、缩进、注释位置等方面保持一致。注释应该尽量放在代码的上方或右侧,而不是在代码中间或下方。
    • 注释应该避免错误和歧义,注释应该准确地反映代码的意图和行为,避免产生歧义和误解。注释应该在代码更新或修改后及时更新,以保证注释与代码的一致性。
    • 注释应该按照一定的规范和格式进行编写,例如使用特定的注释符号、排版方式、注释级别等。在项目中,应该制定一份注释规范和标准,对注释的格式、内容、使用方法等进行明确规定,以保证注释的一致性和可读性。

5、变量

  • 变量的命名规则

    • 命名只能使用英文字母,数字和下划线_,首个字符不能以数字开头

    • 不能使用标点符号或空格

    • 不能使用 Shell 中的关键字

    • 变量名和等号之间不能有空格

    以上这四点是硬性要求,不按上诉规会直接报错,而对于常量或者环境变量的命名一般我们都需要使用全大写字母,每个单词之间使用_分隔(PS:这只是规范,不是规则)

  • Shell中常见的变量

    • 环境变量(Environment Variables):环境变量是Shell进程中的全局变量,可以由Shell启动时设置,也可以在运行时使用export命令设置。常见的环境变量包括PATH、HOME、USER等。
    • 用户定义变量(User-Defined Variables):用户定义变量是Shell脚本中自己定义的变量,可以存储任何类型的数据。变量名通常由字母、数字和下划线组成,但不能以数字开头。
    • 位置参数变量(Positional Parameters):位置参数变量是指Shell脚本中传递给脚本的参数。$0表示脚本本身,$1$2$3…分别表示第一个、第二个、第三个参数,以此类推。
    • 特殊变量(Special Variables):特殊变量是Shell中预定义的一些特殊变量,具有特殊的含义。例如,$?表示上一个命令的返回值,$$表示当前Shell进程的进程号。
    • 只读变量(Read-Only Variables):只读变量是指Shell中不能修改其值的变量,通常用来保存Shell脚本的一些固定值。例如,$RANDOM表示一个随机数,$BASH_VERSION表示当前Shell的版本号等。我们可以通过readonly 关键字来定义只读变量
    • 数组变量(Array Variables):数组变量是一种特殊的变量,可以在一个变量中存储多个值。在Shell中,可以使用下标来访问和修改其中的元素

    主要分为三大类

    • 自定义变量(局部变量):一般是指开发者在Shell脚本中定义的变量,这些变量仅在当前Shell示例中有效,其它Shell示例无法访问,属于局部变量
    • Linux中已定义的环境变量(环境变量):所有的程序,包括Shell启动的程序,都能访问环境变量(比如PATH、HOME……),有些程序需要环境变量来保证其正常运行(必要的时Shell脚本也可以定义环境变量)
    • Shell中的预定义变量(Shell变量):Shell变量是由shell程序设置的特殊变量。Shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
  • 常用操作

    • 查看环境变量

      • set:显示当前shell中自定义的变量,包括用户的环境变量,按变量名称排序。仅在当前Shell有效,可以显示Shell的自定义的变量

        备注:直接 set 是查看当前系统中的所有环境变量,这个输出比较多,一般我们可以搭配管道符+grep命令进行筛选

        Linux的declare命令不加参数和set的作用类似

      image-20230329105147768

      • env:查看所有环境变量,也可以设置环境变量。仅在当前会话中有效,可以显示和设置用户环境变量(Linux中定义的环境变量),用法和set类似
      • export:显示当前导出成用户变量的shell变量(当一个变量被导出时,它将成为子进程的环境变量,这意味着子进程可以访问该变量),并显示变量的属性(是否只读),按变量名称排序,用法和set类似

      set和env都是用来查询环境变量,而export是用来查询导出称用户变量的Shell变量;set作用范围要大于env,set能够查询到env不能查询到的Shell中自定义的变量。以上就是三者之间的主要区别

    • 删除变量unset

      username=ghp # 自定义一个username变量
      set | grep "username" # 查看username变量
      unset username # 删除username变量
      

      注意:只能删除只读变量

    • 只读变量readonly

      myUrl="https://www.runoob.com"
      unset myUrl
      echo $myUrl
      

6、数据类型

  • Shell中的数据类型

    • 字符串(String):字符串是Shell脚本中最常用的数据类型之一。字符串可以使用单引号(')或双引号(")来定义,可以包含任何字符。
    • 数字(Number):Shell脚本中也支持数字类型,包括整数和浮点数。通常使用let命令或者$((expression))语法来计算数字。
    • 数组(Array):数组是一种特殊的数据类型,可以在一个变量中存储多个值。在Shell中,数组可以使用下标来访问和修改其中的元素。
    • 布尔型(Boolean):Shell脚本中没有原生的布尔类型,通常使用0表示假(false),1表示真(true)。
    • 空值(Null):空值表示一个变量没有任何值。在Shell中,可以使用unset命令来清除一个变量的值。

    除了以上常见的数据类型,还有一些特殊的数据类型,如文件描述符命令输出等。掌握这些数据类型可以帮助Shell脚本编程更加灵活和高效。

6.1 字符串

  • 字符串:字符串可以分为三类,单引号字符串双引号字符串不加引号的字符串

    • 单引号字符串

      # hello.sh
      str='this is a string'
      echo $str # this is a string
      

      注意事项

      1. 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;

      2. 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

    • 双引号字符串

      # hello.sh
      your_name="ghp"
      str="my name is \"$your_name\"! \n"
      echo $str # my name is ghp!
      

      如果出现了command not fount,这是由于 hello.sh 编码格式不对,我就踩坑了,=左右一定不能有空格,因为在写Java代码时,写空格写习惯了

      双引号相较于单引号的优点

      1. 可以使用转义符,单引号是直接输出
      2. 可以直接在字符串中使用变量,单引号只能通过拼接
    • 不加引号的字符串

      str=abc
      echo $str # abc
      

      注意:定义的变量不能含有空格

  • 常见的字符串操作

    • 字符串拼接

      your_name="ghp"
      # 使用双引号拼接
      str1="hello, "$your_name" !"
      str2="hello, ${your_name} !"
      echo $str1 # hello, ghp ! 
      echo $str2 # hello, ghp !
      # 使用单引号拼接
      str3='hello, '$your_name' !'
      str4='hello, ${your_name} !'
      echo $str3  # hello, ghp !
      echo $str4  # hello, ${your_name} !
      
    • 获取字符串长度

      string="abcd"
      echo ${#string} # 4
      echo ${#string[0]} # 4
      
    • 获取子字符串

      str="runoob is a great site"
      echo ${str:6:8} # is a gr
      

      备注:从第7个字符开始,第7个字符是b后面的空格,然后往后数8个字符,也就是到 gr 结束runoob[ is a gr]eat site。类似于Python中的切片

    • 查找字符

      str="runoob is a great site"
      echo `expr index "$str" io` # 4
      

      备注:查找字符io,谁先出现就先计算谁,这里o先出现,它是第4个字符,所以输出4

6.2 数组

  • 数组的定义

    数组名=(值1 值2 ... 值n)
    # 示例:
    arr=(1 2 3)
    # 备注:空格的数量没有影响,字符串数组要用引号
    arr=(
    1
    2
    3
    )
    arr[0]=1
    arr[1]=2
    arr[3]=3
    
  • 常见的数组操作

    • 获取数组中的元素

      # 读取数组中的元素
      ${数组名[下标]}
      # 示例
      arr=(1 2 3)
      echo ${arr[1]} # 2
      echo ${arr[@]} # 1 2 3
      
    • 获取数组的长度

      # 取得数组元素的个数
      ${#arr[@]}
      # 或者
      ${#arr[*]}
      # 取得数组单个元素的长度
      ${#arr[下标]}
      

7、参数传递

  • $n:n表示一个正整数,1表示第一个参数,2表示第二个参数……
  • $#:传递到脚本的参数个数
  • $*:显示所有向脚本传递的参数
  • $@:显示所有向脚本传递的参数
  • $$:脚本运行的当前进程ID号
  • $!:后台运行的最后一个进程ID号
  • $-:显示Shell使用的当前选项,与set命令功能相同
  • $?:显示最后命令的退出状态,0没有错误,其它任何值都表明有错误
  • $_ :表示的是打印上一个输入参数行, 当这个命令在开头时, 打印输出文档的绝对路径名

示例

#!/bin/bash
echo "Shell 传递参数实例!";
echo "\$0 执行的文件名:$0";
echo "\$1 第一个参数为:$1";
echo "\$2 第二个参数为:$2";
echo "\$3 第三个参数为:$3";
echo "\$# 传递脚本的参数个数: $#"
echo "\$* 所有传入脚本的参数: $*"
echo "\$@ 所有传入脚本的参数: $@"
echo "\$$ 脚本运行的当前进程ID: $$"
echo "\$! 后台运行的最后一个进程ID: $!"
echo "\$- shell使用的当前选项: $-"
echo "\$? 最后命令退出的状态: $?"
echo "\$_ 上一个输入参数行: $_"
sh test.sh 1 2 "3"
Shell 传递参数实例!
$0 执行的文件名:test.sh
$1 第一个参数为:1
$2 第二个参数为:2
$3 第三个参数为:3
$# 传递脚本的参数个数: 3
$* 所有传入脚本的参数: 1 2 3
$@ 所有传入脚本的参数: 1 2 3
$$ 脚本运行的当前进程ID: 53206
$! 后台运行的最后一个进程ID: 
$- shell使用的当前选项: hB
$? 最后命令退出的状态: 0
$_ 上一个输入参数行: $? 最后命令退出的状态: 0
  • $* $@ 区别

    • 相同点:都是引用所有参数。
    • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 "* " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。
    #!/bin/bash
    echo "-- \$* 演示 ---"
    for i in "$*"; do
        echo $i
    done
    
    echo "-- \$@ 演示 ---"
    for i in "$@"; do
        echo $i
    done
    
    sh test.sh 1 2 3
    -- $* 演示 ---
    1 2 3
    -- $@ 演示 ---
    1
    2
    3
    

8、运算符

Shell 编程支持下面几种运算符

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 逻辑运算符
  • 字符串运算符
  • 文件测试运算符

详情请参考:Shell 基本运算符 | 菜鸟教程 (runoob.com)

  • 计算指令/符号

    image-20230404152818387

  • 算术运算符

    假定变量 a 为 10,变量 b 为 20

    image-20230404094358757

    注意

    1. 条件表达式要放在方括号之间,并且要有空格,例如: [a==b] 是错误的,必须写成 [ a == b ],但是在[]中进行数值计算时,不需要空格,比如[a+b]
    2. *前边必须加反斜杠\才能实现乘法运算
    3. 在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 *"不需要转义符号 \
  • 关系运算符

    假定变量 a 为 10,变量 b 为 20

    image-20230404095031496

    注意:关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

  • 布尔运算符

    假定变量 a 为 10,变量 b 为 20

    image-20230404095301467

  • 逻辑运算符

    假定变量 a 为 10,变量 b 为 20

    image-20230404095334217

  • 字符串运算符

    下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

    image-20230404095409691

  • 文件测试运算符

    image-20230404095600834

    其他检查符:

    • -S: 判断某文件是否 socket。
    • -L: 检测文件是否存在并且是一个符号链接。

9、常用命令

9.1 echo命令

Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。命令格式:

echo [参数] string

参数说明

  1. -n:当指定-n选项时,其后的换行符被抑制;即不会在最后自动换行
  2. -e:当指定-e选项时,则将解释以下反斜杠转义字符

您可以使用echo实现更复杂的输出格式控制。

  • 显示普通字符串:

    echo "It is a test"
    

    这里的双引号完全可以省略,以下命令与上面实例效果一致:

    echo It is a test
    
  • 显示转义字符

    echo "\"It is a test\""
    

    结果将是:

    "It is a test"
    

    同样,双引号也可以省略

  • 显示变量

    read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量

    #!/bin/sh
    read name 
    echo "$name It is a test"
    

    以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:

    [root@www ~]# sh test.sh
    OK                     #标准输入
    OK It is a test        #输出
    
  • 显示换行

    echo -e "OK! \n" # -e 开启转义
    echo "It is a test"
    

    输出结果:

    OK!
    
    It is a test
    
  • 显示不换行

    #!/bin/sh
    echo -e "OK! \c" # -e 开启转义 \c 不换行
    echo "It is a test"
    

    输出结果:

    OK! It is a test
    
  • 显示结果定向至文件

    echo "It is a test" > myfile
    
  • 原样输出字符串,不进行转义或取变量(用单引号)

    echo '$name\"'
    

    输出结果:

    $name\"
    
  • 命令执行结果

    echo `date`
    

    结果将显示当前日期

    Thu Jul 24 10:08:46 CST 2014
    

9.2 printf命令

上一章节我们学习了 Shell 的 echo 命令,本章节我们来学习 Shell 的另一个输出命令 printf。

printf 命令模仿 C 程序库(library)里的 printf() 程序。

printf 由 POSIX 标准所定义,因此使用 printf 的脚本比使用 echo 移植性好。

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n

printf语法格式:

printf  format-string  [arguments...]

参数说明

  1. format-string: 为格式控制字符串

  2. arguments: 为参数列表

示例

#!/bin/bash
printf "Hello, Shell\n"
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
Hello, Shell
姓名     性别   体重kg
郭靖     男      66.12

备注%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。%-4.2f 指格式化为小数,其中 .2 指保留2位小数。

知识拓展:常见的转义符

image-20230404144254425

9.3 test命令

test命令主要用于:数值测试、字符串测试、文件测试

  • 数值测试

    image-20230404144553476

    示例:

    #!/bin/bash
    num1=100
    num2=100
    if test $[num1] -eq $[num2]
    then
        echo '两个数相等!'
    else
        echo '两个数不相等!'
    fi
    
    两个数相等!
    
  • 字符串测试

    image-20230404144543394

    示例:

    #!/bin/bash
    num1="a b"
    num2="ab"
    if test $num1 = $num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
    
    两个字符串不相等!
    
  • 文件测试

    image-20230404144606668

    示例:

    #!/bin/bash
    if test -e /home/ghp/test.sh
    then
        echo '文件已存在!'
    else
        echo '文件不存在!'
    fi
    
    文件已存在!
    

知识拓展:逻辑操作符

Shell 还提供了与 -a(与) 、-o (或)、!(非) 三个逻辑操作符用于将测试条件连接起来,其优先级为: ! 最高, -a 次之, -o 最低

#!/bin/bash
if test ! -e /home/ghp/test.sh -o -e /home/ghp/unexite.sh
then
    echo '至少有一个文件存在!'
else
    echo '两个文件都不存在'
fi
两个文件都不存在

备注:-e /home/ghp/test.sh得到的结果为 真,但是前面有一个 ! 从而导致结果为 假,-o表示或,只有有一个为真就为真,结果-e /home/ghp/unexite.sh 的结果也是 假,两个都为假,最终的结果就为假了

10、流程控制

10.1 条件判断

  • if

    if condition
    then
        command1 
        command2
        ...
        commandN 
    fi
    
  • if else

    if condition
    then
        command1 
        command2
        ...
        commandN
    else
        command
    fi
    

    注意:else中的command不能为空,在Java中是可以的,但是Shell中是不允许的

  • if else if esle

    if condition1
    then
        command1
    elif condition2 
    then 
        command2
    else
        commandN
    fi
    

示例

if 0
then
    echo "条件为真"
else
   # echo "条件为假"
fi

else为空直接报错:

image-20230404152005707

取消注释,就能运算成功了:

image-20230404152152875

10.2 循环

11、函数

Shell中的函数总共非为两大类:有返回值的函数和没有返回值的函数

函数的定义方式:

[ function ] funname [()]

{

    action;

    [return int;]

}

备注:这里的[]表示Shell中的运算符,而是表示这个参数可以省略

示例

#!/bin/bash
# 没有返回值的函数
demoFun(){
    echo "这是我的第一个 shell 函数!"
}
echo "-----demoFun函数开始执行-----"
demoFun
echo "-----demoFun函数执行完毕-----"

# 有返回值的函数
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "$aNum$anotherNum 相加的结果为:"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

image-20230404153736384

#!/bin/bash
# 带参函数
funWithParam(){
    echo "第一个参数为 $1 !"
    echo "第二个参数为 $2 !"
    echo "参数总数有 $# 个!"
    echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3

image-20230404154801954

注意:获取第10个参数是,不能这样写$10,要这样写${10}

12、输入/输出重定向

Linux Shell 重定向分为两种,一种输入重定向,一种是输出重定向;从字面上理解,输入输出重定向就是「改变输入与输出的方向」的意思。

12.0 前置知识

  • 什么是输入重定向和输出重定向

    输入方向就是数据从哪里流向程序。数据默认从键盘流向程序,如果改变了它的方向,数据就从其它地方流入,这就是输入重定向。输出方向就是数据从程序流向哪里。数据默认从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向

  • 什么是标准输入设备和标准输出设备

    计算机的硬件设备有很多,常见的输入设备有键盘、鼠标、麦克风、手写板等,输出设备有显示器、投影仪、打印机等。不过,在 Linux 中,标准输入设备指的是键盘标准输出设备指的是显示器

  • 什么是文件描述符

    Linux 中一切皆文件,包括标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件。

    为了表示和区分已经打开的文件,Linux 会给每个文件分配一个 ID,这个 ID 就是一个整数,被称为文件描述符(File Descriptor)。

    image-20230404160509743

12.1 输出重定向

Bash 支持的输出重定向符号:

image-20230404162416263

备注:在输出重定向中,>代表的是覆盖,>>代表的是追加

注意

  1. 输出重定向的完整写法其实是fd>file或者fd>>file,其中 fd 表示文件描述符,如果不写,默认为 1,也就是标准输出文件。当文件描述符为 1 时,一般都省略不写,如上表所示;当然,如果你愿意,也可以将command >file写作command 1>file,但这样做是多此一举。当文件描述符为大于 1 的值时,比如 2,就必须写上。

  2. fd>之间不能有空格,否则 Shell 会解析失败;>file之间的空格可有可无。为了保持一致,我习惯在>两边都不加空格。

    错误示例:

    echo "你好" 1 >log.txt
    

    在log.txt中你会发现是

    "你好" 1
    

    这是因为上面1和>之间存在空格,它的语句变成了 echo “你好” 1 1>log.txt

示例

# 将 Hello World! 输出到 test 文件(test文件不需要先创建,Shll会自动在当前目录创建test文件)
echo "Hello World\!" > test
# 查看test文件中的内容
cat test
Hello World\!
for str in "abcd 123 张三 !@"
do
    echo $str >> test  # 将输入结果以追加的方式重定向到文件
done

image-20230404164324087

12.2 输入重定向

Bash支持的输入重定向:

image-20230404164603923

PS:和输出重定向类似,输入重定向的完整写法是fd<file,其中 fd 表示文件描述符,如果不写,默认为 0,也就是标准输入文件。

示例

准备工作

需要熟悉wc命令(不知道为什么看到这个命令我脑子里蹦出来一句wc)

wc  [参数]  [文件名]

参数说明:-c选项统计字节数;-w选项统计单词数;-l选项统计行数

之前用过的test文件:

Hello World\!
abcd 123 张三 !@

示例1:获取文件的行数

wc -l < test
2 # 获取test文件的行数

示例2:逐行读取文件

#!/bin/bash
while read str
do
    echo $str
done < test

这种输入重定向的写法叫做代码重定向

示例3:统计用户在终端输入的文本的单词或数字数量

[ghp@node1 ~]$ wc -w << end
> 1 2 3
> 4\?
> end
4 # -w只统计单词和数字
  • Here Document:Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

    command << delimiter
        document
    delimiter
    

    它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command

    注意:结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。开始的delimiter前后的空格会被忽略掉。

    示例:

    cat << EOF
    欢迎来到
    菜鸟教程
    www.runoob.com
    EOF
    
    欢迎来到
    菜鸟教程
    www.runoob.com
    
  • /dev/null 文件:/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

    command > /dev/null
    

13、文件包含

所谓的“文件包含”是指可以在一个文件中引入其它的文件。比如我们可以在Shell脚本中引用其它脚本文件

. filename   # 注意点号(.)和文件名中间有一空格source filename

示例

脚本一:

#!/bin/bash
name="ghp"

脚本二:

#!/bin/bash

#使用 . 号来引用test1.sh 文件
. ./test1.sh

# 或者使用以下包含文件代码
# source ./test1.sh

echo "我的名字:$name"

执行脚本二

我的名字:ghp

参考资料

  • Shell 教程 | 菜鸟教程 (runoob.com)
  • Shell脚本:Linux Shell脚本学习指南(超详细) (biancheng.net)
  • Shell编程: shell脚本5种执行方式血煞长虹的博客-CSDN博客
  • Shell环境变量set、env、export_訾零的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/477296.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实验六~Web事件处理与过滤器

1. 创建一个名为exp06的Web项目&#xff0c;编写、部署、测试一个ServletContext事件监听器。 BookBean代码 package org.example.beans;import java.io.Serializable;/*** Created with IntelliJ IDEA.* Description:* User: Li_yizYa* Date: 2023—04—29* Time: 18:39*/ Su…

DDD系列:二、应用架构设计演变

作用: ​ 通过规定一个固定的架构设计&#xff0c;可以让团队内有一个统一的开发规范&#xff0c;降低沟通成本&#xff0c;提升效率和代码质量。 目标&#xff1a; ​ 在做架构设计时&#xff0c;一个好的架构应该需要实现以下几个目标&#xff1a; 独立于UI&#xff1a;前…

02-Vue技术栈之基础篇(下)

目录 1、class 与 style 绑定1.1 理解1.2 class 绑定1.3 style绑定1.4 代码示例 2、条件渲染2.1 v-if2.2 v-show2.3 注意事项2.4 代码示例 3、列表渲染3.1 基本列表3.2 key的原理3.2.1 虚拟DOM中key的作用&#xff1a;3.2.2 对比规则&#xff1a;3.2.3 用index作为key可能会引发…

防火墙GRE和NAT

要求&#xff1a; Pc2和pc3之间互通&#xff1b;做gre pc2与pc3访问公网pc1要做地址转换 基本配置&#xff1a;省略&#xff0c;小孩子都会 这里查看效果&#xff1a; 区域划分 fw1&#xff1a; fw2&#xff1a; 接口地址划分&#xff1a; fw1&#xff1a; fw2&#xff1a;…

武汉大学惯性导航课程合集【2021年秋】1.1惯性导航和惯性器件

重力外力加速度 机械阻尼换为电阻尼&#xff0c;带宽提高取决于控制器响应速度 右方是不平衡跷跷板&#xff0c;测量顶面电容 机械中测量角速度的旋转编码器&#xff0c;测速电机测量的两个看得见实际物体的转子定子相对角速度&#xff0c;但是陀螺是相对于惯性参考系&#xf…

【YOLO系列】YOLOv6论文超详细解读(翻译 +学习笔记)

前言 YOLOv6 是美团视觉智能部研发的一款目标检测框架&#xff0c;致力于工业应用。论文题目是《YOLOv6: A Single-Stage Object Detection Framework for Industrial Applications》。 本框架同时专注于检测的精度和推理效率&#xff0c;在工业界常用的尺寸模型中&#xff…

如何让 Edge 浏览器更干净!

如果你也喜欢 Edge 或想要尝试迁移&#xff0c;本文介绍一些能够让 Edge 浏览器体验更加干净、纯粹的设置技巧。 洗白新标签页 Edge 的新标签页提供了多种页面设置方案&#xff0c;在没有安装第三方新标签页扩展的前提下&#xff0c;我们可以在默认新标签页右上角的齿轮设置中…

【MCS-51】时钟电路和复位

单片机的处理器内部具有众多模块&#xff0c;但是要想协调这些模块统一工作并不是一件易事。为了确保各部分能够统一有序工作&#xff0c;因为单片机已经是一个同步时序电路&#xff0c;所以要想让它内部能够有序工作&#xff0c;我们需要从外部输入一个时钟信号。 目录 &am…

MyBatis凭什么征服SpringBoot ?

1、MyBatis的优势 众所周知&#xff0c;MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。通过xml映射到接口&#xff0c;使开发者使用接口的方式就能够轻松的映射、解析、执行xml中的SQL。MyBatis 消除了几乎所有的JDBC代码和参数的手工设…

No.052<软考>《(高项)备考大全》【冲刺6】《软考之 119个工具 (4)》

《软考之 119个工具 &#xff08;4&#xff09;》 61.人际交往:62.组织理论:63.预分派:64.谈判:65.招募:66.虚拟团队:67.多标准决策分析:68.人际关系技能:69.培训:70.团队建设活动:71.基本规则:72.集中办公:73.认可与奖励:74.人事评测工具:75.观察和交谈:76.项目绩效评估:77.冲…

Linux学习[8]查找文件指令:which whereis locate find

文章目录 前言1. which2. whereis3. locate4. find总结&#xff1a; 前言 之前在弄交叉编译的时候需要找到gcc&#xff0c;gdb什么的在哪里&#xff1b;涉及到了查找文件指令。 这里对linux中的查找指令进行总结 1. which which指令一般用来寻找可执行文件的路径&#xff0c;…

OpenCV实战(20)——图像投影关系

OpenCV实战&#xff08;20&#xff09;——图像投影关系 0. 前言1. 相机成像原理2. 图像对的基本矩阵3. 完整代码小结系列链接 0. 前言 数码相机通过将光线通过镜头投射到图像传感器上来捕捉场景产生图像。由于通过将 3D 场景投影到 2D 平面上形成图像&#xff0c;因此场景与其…

时序预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元时间序列预测

时序预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元时间序列预测 目录 时序预测 | MATLAB实现BO-CNN-GRU贝叶斯优化卷积门控循环单元时间序列预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 基于贝叶斯(bayes)优化卷积神经网络-门控循环单元(CNN-GR…

2023年人工智能GPT-4时代,最新13个ChatGPT商业市场AIGC应用正在掀起革命性变革!

目录 前言ChatGPT商业应用——LLM是星辰大海1. 研究背景1.1 研究背景1.2 研究方法 2. 商业应用和案例分析2.1 工具层ChatGPT搜索ChatGPT办公ChatGPT教育 2.2 行业层ChatGPT游戏ChatGPT音乐ChatGPT零售电商ChatGPT广告营销ChatGPT媒体新闻ChatGPT金融ChatGPT医疗ChatGPT设计Chat…

AI绘画能力的起源:通俗理解VAE、扩散模型DDPM、ViT/Swin transformer

前言 2018年我写过一篇博客&#xff0c;叫&#xff1a;《一文读懂目标检测&#xff1a;R-CNN、Fast R-CNN、Faster R-CNN、YOLO、SSD》&#xff0c;该文相当于梳理了2019年之前CV领域的典型视觉模型&#xff0c;比如 2014 R-CNN2015 Fast R-CNN、Faster R-CNN2016 YOLO、SSD2…

Linux命令集(Linux网络连接管理命令--ifconfig指令篇)

Linux命令集&#xff08;Linux网络连接管理命令--ifconfig指令篇&#xff09; Linux网络连接管理命令集&#xff08;ifconfig指令篇&#xff09;1. ifconfig(interface configuration)1. 信息显示2. 接口配置 Linux网络连接管理命令集&#xff08;ifconfig指令篇&#xff09; 如…

C++Primer第五版【阅读笔记】

CPrimer第五版 阅读笔记 第1章开始1.1 编写一个简单的C程序1.1.1 编译、运行程序 1.2 初识输入输出1.3 注释简介1.4 控制流1.4.1 while语句1.4.2 for语句1.4.3 读取数量不定的输入数据1.4.4 if语句 1.5 类简介1.5.1 Sales_item 类1.5.2 初识成员函数 1.6 书店程序第一章小结 第…

【Linux入门】linux指令(1)

【Linux入门】linux指令&#xff08;1&#xff09; 目录 【Linux入门】linux指令&#xff08;1&#xff09;操作系统登录服务器Linux下的基本指令ls指令pwd指令Linux路径分割符 /cd指令touch指令mkdir指令&#xff08;重要&#xff09;rmdir指令&&rm指令&#xff08;重…

4.30下周美联储携非农来袭黄金多空该如何布局?

近期有哪些消息面影响黄金走势&#xff1f;下周黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周五(4月28日)当周金价维持震荡交投&#xff0c;金价基本持稳于2000美元下方。支撑和打压金价的因素参半。经济衰退的担忧&#xff0c;以及避险情绪支持金价&#x…

Fabric.js 讲解官方demo:Stickman

theme: smartblue 本文简介 戴尬猴&#xff0c;我是德育处主任 Fabric.js 官网有很多有趣的Demo&#xff0c;不仅可以帮助我们了解其功能&#xff0c;还可以为我们提供创意灵感。其中&#xff0c;Stickman是一个非常有趣的例子。 先看看效果图 从上图可以看出&#xff0c;在拖拽…