第十章 认识与学习BASH

发布时间 2023-07-31 11:13:09作者: Evan-whc

第十章 认识与学习BASH

10.1 认识BASH这个Shell

  我们在第一章Linux是什么当中提到了:管理整个计算机硬件的其实是操作系统的核心(kernel),这个核心是需要被保护的!所以我们一般使用者就只能通过shell来跟核心沟通,以让核心达到我们所想要达到的工作。那么系统有多少shell可用呢?为什么我们要使用bash啊?下面分别来谈一谈喔!

10.1.4 Bash shell的功能

  bash主要的优点有下面几个:

  • 命令编修能力(history)
  • 命令与文件补全功能
  • 命令别名设置功能
  • 工作控制、前景背景控制
  • 程序化脚本:(shell script)
  • 万用字符:(Wildcard)

10.1.5 查询指令是否为Bash shell的内置命令:type

  为了方便shell的操作,其实bash已经内置了很多指令了,例如上面提到的cd,还有例如umask等等的指令,都是内置在bash当中的呢!

type [-tpa] name
选项与参数:
:不回任何选项与参数时,type会显示出name是外部指令还是bash内置指令
-t: file表示为外部指令,alias表示为别名,builtin表示内置指令
-p: 如果后面接的name为外部指令时,才会显示完整文件名
-a: 会由PATH变量定义的路径中,将所有含name的指令都列出来,包含alias

10.1.6 指令的下达与快速编辑按钮

  如果要输入的指令太长,可以使用【\】来将【Enter】这个按键跳脱开来!让【Enter】不再具有【开始执行】的功能!好让指令可以继续在下一行输入。

cp /var/spool/mail/root /etc/crontab \
> /etc/fstab /root

  另外,当你所需要下达的指令特别长,或者你输入了一串错误的指令时,你想要快速的将这串指令整个删除掉,一般来说,我们都是按下删除键的。有没有其他的快速组合键可以协助的呢?是有的,常见的有下面这些:

组合键 ctrl+k
ctrl+u/ctrl+k 分别是从光标处向前删除指令串(ctrl+u),及向后删除指令串ctrl+k
ctrl+a/ctrl+e 分别是让光标移动到整个指令串的最前面(ctrl+a),或最后面(ctrl+e)

10.2 Shell的变量功能

10.2.2 变量的取用与设置:echo,变量设置规则,unset

  你可以利用echo这个指令来取用变量,但是,变量在被取用时,前面必须要加上钱字号"$"才行。如 echo $PATH

  变量的设置规则:

  • 变量与变量的内容以一个等号"="来连接
  • 等号两边不能直接接空白字符
  • 变量名称只能是英文字母与数字,但是开头字符不能是数字
  • 变量内容若有空白字符可使用双引号或单引号将变量内容结合起来,但
    • 双引号内的特殊字符如$等,可以保有原本的特性
    • 单引号内的特殊字符则仅为一般字符
  • 可用跳脱字符“\”将特殊符号变成一般字符
  • 在一串指令的执行中,还需要借助由其他额外的指令所提供的信息时,可以使用反单引号或$(指令)。
  • 若该变量为扩增变量内容时,则可用"$变量名称"或${变量}累加内容
  • 若该变量需要在其他子程序执行,则需要以export来使变量变成变量:"export PATH"
  • 通常大写字符为系统默认变量,自行设置变量可以使用小写字符,方便判断。
  • 取消变量的方法为使用unset

环境变量的功能

  问一下,目前我的shell环境中,有多少默认的环境变量啊?我们可以利用两个指令来查阅,分别是env与export呢!

  • 用env观察环境变量与常见环境变量说明
    env

    • SHELL: 目前这个环境的SHELL
    • HSITORY: 历史命令
    • MAIL: 邮件信箱文件
    • PATH: 可执行文件搜寻路径
    • LANG: 语系数据
    • RANDOM: 随机乱数(0~32768)万一我想要使用0~9之间的数据呢?利用declare宣告数值类型,然后再这样做就可以了:declare -i number=$RANDOM*10/32768
  • 用set观察所有变量(含环境变量与自订变量)
      bash可不只有环境变量喔,还有一些与bash操作接口有关的变量,以及使用者自己定义的变量存在的。那么这些变量如何观察呢、这个时候应得要使用set这个指令了。set除了环境变量之外,还会将bash内的变量通通显示出来哩!其中比较重要的大概有几下几个

    • PS1:提示字符的设置
      • \d:显示出“星期 月 日”的日期格式
      • \H:完整的主机名称
      • \h:仅取主机名称在第一个小数点之前的名字
      • \t: 显示时间,24小时完整格式
      • \T: 显示时间,12小时完整格式
      • \A: 显示时间,24小时简洁格式
      • @: 显示时间,12小时简洁格式
      • \u: 目前使用者的帐号名称
      • \v: BASH的版本信息
      • \w:完整的工作目录名称
      • \W: 利用basename函数取得工作目录名称
      • #:下达的第几个指令
      • $: 提示字符
  • export:自订变量转成环境变量
      谈了env与set现在知道有所谓的环境变量与自订变量,那么这两者之间有啥差异呢?其实这两者的差异在于“该变量是否会被子程序所继续引用”啦!

10.2.4 影响显示结果的语系变量(locale)

  我们的Linux到底支持了多少的语系呢?这可以由locale这个指令来查询到喔!
locale -a

locale #查看可修改的相关变量

10.2.6 变量键盘读取、陈列与宣告:read,array,declare

  • read
    要读取来自键盘输入的变量,就是用read这个指令了。
read [-pt] variable
选项与参数:
-p: 后面可以接提示字符
-t: 可以等待的秒数
  • declare/typeset
    declare或typeset是一样的功能,就是在“宣告变量的类型”。如果使用declare后面并没有接任何参数,那么bash就会主动的将所有的变量名称与内容通通叫出来,就好像使用set一样啦!那么declare还有什么语法呢?
declare [-aixr] variable
选项与参数:
-a: 将后面名为variable的变量定义成为阵列(array)类型
-i: 将后面名为variable的变量定义成为整数数字(integer)类型
-x: 与export一样,将后面的variable变成环境变量
-r: 将变量设置成为readonly类型,该变量不可被更改内容,也不能unset

10.3 命令别名与历史命令

命令别名设置:alias,unalias

alias lm='ls -al | more'
unalias lm

10.3.2 历史命令:history

history [n]
history [-c]
history [-raw] histfiles
选项与参数:
n: 数字,列出最近的n笔命令表
-c: 消除所有的history

!number
!command
!!
选项与参数:
number: 执行第几笔命令的意思
command: 由最近的指令向前搜寻【指令串开头为command】的那个指令并执行
!!: 执行上一个指令

10.4 Bash Shell的操作环境

10.5 数据流重导向

  数据流重导向(redirect)由字面上的意思来看,好像就是将“数据给他导到其他地方去”的样子?没错~数据流重导向就是将某个指令执行后应该要出现的屏幕上的数据,给他输出到其他的地方,例如文件或是装置!

  • standard output与standard error output
      简单的说,标准输出指的是“指令执行所回传的正确的讯息”,而标准错误输出可理解为“指令执行失败后,所回传的错误讯息”。
      standard output与standard error output所用的特殊字符如下所示:

    1. 标准输入(stdin):代码为0,使用<或<<
    2. 标准输出(stdout):代码为1,使用>或>>
    3. 标准错误输出(stderr):代码为2,使用2>或2>>
      ll / > ~/rootfile
        如果仅存在>时,则代表预设的代码1啰!也就是说:
    • 1>:以覆盖的方式将【正确的数据】输出到指定的文件或装置上
    • 1>>:以累加的方式将【正确的数据】输出到指定的文件或装置上
    • 2>:以覆盖的方式将【错误的数据】输出到指定的文件或装置上
    • 2>>:以累加的方式将【错误的数据】输出到指定的文件或装置上
  • /dev/null垃圾桶黑洞装置与特殊写法
    find /home -name .bashrc 2> /dev/null#只有stdout会显示在屏幕上,stderr被丢弃了

  • standard input:<与<<
      简单来说,就是“将原来由需要键盘输入的数据,改由文件内容来取代”的意思。例如:

cat > catfile
testing #键盘输入两行数据
cat file test
#这里按下ctrl+d来离开输入

  如何使用<<来结束输入:

cat > catfile << "eof"
>This is a test.
>OK now top
>eof #输入此关键词,立刻就结束而不用ctrl+d

10.5.2 命令执行的判断依据:;,&&,||

  • cmd;cmd (不考虑命令的相关性的连结指令下达)
    sync;sync;sync;shutdown -h now
  • $?(指令回传值)与&&或
    $?是指令回传值,是指“若前一个指令执行的结果为正确,在Linux底下会回传一个$?=0的值”。那么我们如何透过这个回传值来判断后续的指令是否要执行呢?这应得要籍由&&及||的帮忙了。
指令下达情况 说明
cmd1&&cmd2 1. 若cmd1执行完毕且正确执行,则开始执行cmd2 2. 若cmd1执行完毕且为错误,则cmd2不执行
cmd1|| cmd2 1. 若cmd1执行成功,则cmd2不执行。 2. 若cmd1执行错误,则执行cmd2

10.6 管线命令(pipe)

  管线命令使用的是【|】这个界定符号!这个管线命令仅能处理经由前一个指令传来的正确信息,也就是standard output的信息,对于standard error并没有直接处理的能力。
ls -al /etc | less
  管线命令主要有两个比较需要注意的地方:

  • 管线命令仅会处理standard output,对于standard output会予以忽略
  • 管线命令必须要能够接受来自前一个指令的数据成为standard input继续处理才行

10.6.1 撷取命令:cut,grep

  什么是撷取命令啊?说穿了,就是将一段数据经过分析后,取出我们所要的。或者是经由分析关键词,取得我们所想要的那一行!一般来说,撷取信息通常是针对“一行一行”来分析的。

  • cut
cut -d '分隔字符' -f fields
cut -c 字符区间
选项与参数:
-d: 后面接分隔字符。与-f一起使用
-f: 依据-d的分隔字符将一段信息分区成为数段,用-f取出第几段的意思
-c: 以字符的单位取出固定字符区间
范例:
echo ${PATH} | cut -d ':' -f 5
  • grep
      刚刚的cut是将一行信息当中,取出某部分我们想要的,而grep则是分析一行讯息,若当中有我们所需要的信息,就将该行拿出来~简单的语法是这样的:
grep [-acinv] [--color=auto] '搜寻字符串' filename
选项与参数:
-a: 将binary文件以text文件的方式搜寻数据
-c: 计算找到'搜寻字符串'的次数
-i: 忽略大小写的不同,所以大小写视为相同
-n: 顺便输出行号
-v: 反向选择,亦即显示出没有'搜寻字符串'内容的那一行!
--color=auto:可以将找到的关键词部分加上颜色的显示喔!

10.6.2 排序命令:sort,wc,uniq

  • sort
sort [-fbMnrtuk] [file or stdin]
选项与参数:
-f: 忽略大小写
-b: 忽略最前面的空格符
-M:以月份的名字来排序
-n: 使用纯数字进行排序,默认是以文字形态排序
-r: 反向排序
-u: 就是uniq,相同的数据中,仅出现一行代表
-t: 分隔符,预设是使用【tab】键来分隔
-k:以哪个区间(field)来进行排序
  • uniq
uniq [-ic]
选项与参数:
-i: 忽略大小写字符的不同
-c: 进行计数
  • wc 计算字符数
wc [-lwm]
选项与参数:
-l: 仅列出行
-w: 仅列出多少字(英文单字)
-m: 多少字符

10.6.3 双向重导向:tee

tee [-a] file
选项与参数:
-a: 以累加的方式,将数据加入file当中!

10.6.6 参数代换:xargs

  这个玩意儿就是在产生某个指令的参数的意思!

xargs [-0epn] command
选项与参数:
-0:如果输入的stdin含有特殊字符,例如`,\,空格键等字符时,这个参数可以将他还原成一般字符。
-e: 这个是EOF(end of file)的意思。后面可以接一个字符串,当xargs分析到这个字符串时,就会停止继续工作。
-p: 在执行每个指令的argument时,都会询问使用者的意思。
-n: 后面接次数,每次command指令执行时,要使用几个参数的意思。
当xargs后面没有接任何的指令时,默认是以echo来进行输出喔!
范例:
cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id

10.6.7 关于减号-的用途

  在管线命令中,常常会使用到前一个指令的stdout作为这次的stdin,某些指令需要用到文件名(例如tar)来进行处理时,该stdin与stdout可以利用减号“-”来替代,举例来说:

mkdir /tmp/homeback
tar -cvf - /home | tar -xvf - -C /tmp/homeback

  我将/home里面的文件给他打包,但打包的数据不是记录到文件,而是传送到stdout;经过管线后,将tar -cvf - /home传送给后面的tar -xvf -。后面的这个-则是取用前一个指令的stdout,因此,我们就不需要使用filename了!这是很常用的例子喔!