Linux基础篇-第十章-BASH 这个 Shell

常用指令

type [-tpa] name :查询指令是否为 Bash shell 的内建命令
      :不加任何选项与参数时,type 会显示出 name 是外部指令还是 bash 内建指令
      -t :当加入 -t 参数时,type 会将 name 以底下这些字眼显示出他的意义:
           file :表示为外部指令;
           alias :表示该指令为命令别名所设定的名称;
           builtin :表示该指令为 bash 内建的指令功能;
      -p :如果后面接的 name 为外部指令时,才会显示完整文件名;
      -a :会由 PATH 变量定义的路径中,将所有含 name 的指令都列出来,包含 alias 

[ctrl]+u/[ctrl]+k : 分别是从光标处向前删除指令串 ([ctrl]+u) 及向后删除指令串 ([ctrl]+k)

[ctrl]+a/[ctrl]+e : 分别是让光标移动到整个指令串的最前面 ([ctrl]+a) 或最后面 ([ctrl]+e)

echo $name 或  echo ${name} :有『显示、印出』的意思

unset :取消变量的方法

env :列出目前的 shell 环境下的所有环境变量与其内容

set :用 set 观察所有变量 (含环境变量与自定义变量)
      -u :预设不启用。若启用后,当使用未设定变量时,会显示错误讯息;
      -v :预设不启用。若启用后,在讯息被输出前,会先显示讯息的原始内容;
      -x :预设不启用。若启用后,在指令被执行前,会显示指令内容(前面有 ++ 符号)
      -h :预设启用。与历史命令有关;
      -H :预设启用。与历史命令有关;
      -m :预设启用。与工作管理有关;
      -B :预设启用。与刮号 [] 的作用有关;
      -C :预设不启用。若使用 > 等,则若文件存在时,该文件不会被覆盖。

read [-pt] variable :读取来自键盘输入的变量
      -p :后面可以接提示字符!
      -t :后面可以接等待的『秒数!』这个比较有趣~不会一直等待使用者啦!

declare 或 typeset :是一样的功能,就是在『宣告变量的类型』
      declare:
      -a :将后面名为 variable 的变量定义成为数组 (array) 类型
      -i :将后面名为 variable 的变量定义成为整数数字 (integer) 类型
      -x :用法与 export 一样,就是将后面的 variable 变成环境变量;
      -r :将变量设定成为 readonly 类型,该变量不可被更改内容,也不能 unset
      -p :可以单独列出变量的类型

ulimit :与文件系统及程序的限制关系
      -H :hard limit ,严格的设定,必定不能超过这个设定的数值;
      -S :soft limit ,警告的设定,可以超过这个设定值,但是若超过则有警告讯息。
             在设定上,通常 soft 会比 hard 小,举例来说,soft 可设定为 80 而 hard
             设定为 100,那么你可以使用到 90 (因为没有超过 100),但介于 80~100 之间时,
             系统会有警告讯息通知你!
      -a :后面不接任何选项与参数,可列出所有的限制额度;
      -c :当某些程序发生错误时,系统可能会将该程序在内存中的信息写成文件(除错用),
             这种文件就被称为核心文件(core file)。此为限制每个核心文件的最大容量。
      -f :此 shell 可以建立的最大文件容量(一般可能设定为 2GB)单位为 Kbytes
      -d :程序可使用的最大断裂内存(segment)容量;
      -l :可用于锁定 (lock) 的内存量
      -t :可使用的最大 CPU 时间 (单位为秒)  
      -u :单一用户可以使用的最大程序(process)数量。

alias 指令别名='指令' : 创建指令别名

unalias 指定别名 :取消命令别名

history :显示历史命令
      -n :数字,意思是『要列出最近的 n 笔命令行表』的意思!
      -c :将目前的 shell 中的所有 history 内容全部消除
      -a :将目前新增的 history 指令新增入 histfiles 中,若没有加 histfiles , 则预设写入 ~/.bash_history
      -r :将 histfiles 的内容读到目前这个 shell 的 history 记忆中;
      -w :将目前的 history 记忆内容写入 histfiles 中!

       history:我们可以利用相关的功能来帮我们执行命令
       !number :执行第几笔指令的意思;
       !command :由最近的指令向前搜寻『指令串开头为 command』的那个指令,并执行;
       !! :就是执行上一个指令(相当于按↑按键后,按 Enter)

source :读入环境配置文件的指令

数据流重

< 与<<   1>与1>>  2>与2>> :数据流重导向

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

管线命令

cut :这个指令可以将一段讯息的某一段给他『切』出来~ 处理的讯息是以『行』为单位
      -d :后面接分隔字符。与 -f 一起使用;
      -f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思;
      -c :以字符 (characters) 的单位取出固定字符区间;

grep [-acinv] [--color=auto] '搜寻字符串' filename :分析一行讯息, 若当中有我们所需要的信息,就将该行拿出来
      -a :将 binary 文件以 text 文件的方式搜寻数据
      -c :计算找到 '搜寻字符串' 的次数
      -i :忽略大小写的不同,所以大小写视为相同
      -n :顺便输出行号
      -v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行!
      --color=auto :可以将找到的关键词部分加上颜色的显示喔!

sort [-fbMnrtuk] [file or stdin] : 排序(sort 是预设『以第一个』数据来排序,且默认是以『文字』型态来排序)
      -f :忽略大小写的差异,例如 A 与 a 视为编码相同;
      -b :忽略最前面的空格符部分;
      -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
      -n :使用『纯数字』进行排序(默认是以文字型态来排序的);
      -r :反向排序;
      -u :就是 uniq ,相同的数据中,仅出现一行代表;
      -t :分隔符,预设是用 [tab] 键来分隔;
      -k :以那个区间 (field) 来进行排序的意思

uniq [-ic] :将重复的资料仅列出一个显示
      -i :忽略大小写字符的不同;
      -c :进行计数

wc [-lwm] :计算输出的讯息的整体数据,输出的三个数字中,分别代表: 『行、字数、字符数』
      -l :仅列出行;
      -w :仅列出多少字(英文单字);
      -m :多少字符;

tee [-a] file :tee 会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的,其实就是stdout ,那就可以让下个指令继续处理
      -a :以累加 (append) 的方式,将数据加入 file 当中!

tr [-ds] SET1 ... :删除一段讯息当中的文字,或者是进行文字讯息的替换
      -d :删除讯息当中的 SET1 这个字符串;
      -s :取代掉重复的字符!

join [-ti12] file1 file2 :处理『两个文件当中,有 "相同数据" 的那一行,才将他加在一起』
      -t :join 默认以空格符分隔数据,并且比对『第一个字段』的数据,如果两个文件相同,则将两笔数据联成一行,且第一个字段放在第一个!
      -i :忽略大小写的差异;
      -1 :这个是数字的 1 ,代表『第一个文件要用那个字段来分析』的意思;
      -2 :代表『第二个文件要用那个字段来分析』的意思。

paste :将两行贴在一起,且中间以 [tab] 键隔开 
      -d :后面可以接分隔字符。预设是以 [tab] 来分隔的!
      - :如果 file 部分写成 - ,表示来自 standard input 的资料的意思。

expand :将 [tab] 按键转成空格键
      -t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空格键取代。 我们也可以自行定义一个 [tab] 按键代表多少个字符呢!

split [-bl] file PREFIX :依据文件大小或行数来分区,就可以将大文件分区成为小文件
      -b :后面可接欲分区成的文件大小,可加单位,例如 b, k, m 等;
      -l :以行数来进行分区。
      PREFIX :代表前导符的意思,可作为分区文件的前导文字。

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

Bash shell 的功能

命令编修能力 (history):

他能记忆使用过的指令,因为我只要在指令列按『上下键』就可以找到前/后一个输入的指令!~/.bash_history 记录的是前一次登入以前所执行过的指令, 而至于这一次登入所执行的指令都被暂存在内存中,当你成功的注销系统后,该指令记忆才会记录到 .bash_history 当中!

命令与文件补全功能: ([tab] 按键的好处):

[Tab] 接在一串指令的第一个字的后面,则为命令补全;
[Tab] 接在一串指令的第二个字以后时,则为『文件补齐』!
若安装 bash-completion 软件,则在某些指令后面使用 [tab] 按键时,可以进行『选项/参数的补齐』功能!

命令别名设定功能: (alias)

你可以在指令列输入 alias 就可以知道目前的命令别名有哪些了!也可以直接下达命令来设定别名:

alias lm='ls -al' : lm 会等于 ls -al 这样的一个功能
工作控制、前景背景控制: (job control, foreground, background

可以让我们随时将工作丢到背景中执行!而不怕不小心使用了[Ctrl] + c 来停掉该程序!

程序化脚本: (shell scripts)

在 Linux 底下的 shell scripts则发挥更为强大的功能,可以将你平时管理系统常需要下达的连续指令写成一个文件, 该文件并且可以透过对谈交互式的方式来进行主机的侦测工作!也可以藉由 shell 提供的环境变量及相关指令来进行设计!整个设计下来几乎就是一个小型的程序语言了。

通配符: (Wildcard) :

除了完整的字符串之外, bash 还支持许多的通配符来帮助用户查询与指令下达。 举例来说,想要知道 /usr/bin 底下有多少以 X 为开头的文件吗?使用:『 ls -l /usr/bin/X* 』就能够知道。此外,还有其他可供利用的通配符。

Shell 的变量功能

什么是变量?

我们可以『用一个简单的 "字眼" 来取代另一个比较复杂或者是容易变动的数据。

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

变量的设定规则:

  1. 变量与变量内容以一个等号『=』来连结,如下所示:
    『myname=VBird』

  2. 等号两边不能直接接空格符,如下所示为错误:
    『myname = VBird』或『myname=VBird Tsai』

  3. 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
    『2myname=VBird』

  4. 变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来,但

双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
   『var="lang is $LANG"』则『echo $var』可得『lang is zh_TW.UTF-8』
单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
   『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』
  1. 可用跳脱字符『 \ 』将特殊符号(如 [Enter], $, \ , 空格符, ' 等)变成一般字符,如:
    『myname=VBird\ Tsai』

  2. 在一串指令的执行中,还需要藉由其他额外的指令所提供的信息时,可以使用反单引号『指令』或 『$(指令)』。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的设定:

『version=$(uname -r)hello』再『echo $version』可得『3.10.0-229.el7.x86_64』

其实上面的指令可以说是作了两次动作,亦即是:
1. 先进行反单引号内的动作『uname -r』并得到核心版本为 3.10.0-229.el7.x86_64
2. 将上述的结果带入到内容,故得内容为:『3.10.0-229.el7.x86_64hello』
  1. 若该变量为扩增变量内容时,则可用 "{变量} 累加内容,如下所示:
『PATH="$PATH":/home/bin』或『PATH=${PATH}:/home/bin』
  1. 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量:
    『export PATH』

  2. 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;

  3. 取消变量的方法为使用 unset :『unset 变量名称』例如取消 myname 的设定:
    『unset myname』

环境变量的功能

环境变量可以帮我们达到很多功能~包括家目录的变换啊、提示字符的显示啊、执行文件搜寻的路径等等, 目前我的 shell 环境中, 有多少默认的环境变量啊?我们可以利用两个指令来查阅,分别是 env 与 export!

PS1:(提示字符的设定)
\d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"
\H :完整的主机名。举例来说,『study.centos.vbird』
\h :仅取主机名在第一个小数点之前的名字,如主机则为『study』后面省略
\t :显示时间,为 24 小时格式的『HH:MM:SS』
\T :显示时间,为 12 小时格式的『HH:MM:SS』
\A :显示时间,为 24 小时格式的『HH:MM』
\@ :显示时间,为 12 小时格式的『am/pm』样式
\u :目前使用者的账号名称,如『dmtsai』;
\v :BASH 的版本信息,如测试主机版本为 4.2.46(1)-release,仅取『4.2』显示
\w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;
\W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。
\# :下达的第几个指令。
\$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ ~

PS1颜色配置

体代码 背景代码 颜色
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

常用颜色(上一个PS1指令为下一个指令颜色)

image.png

$:(关于本 shell 的 PID)
目前这个 Shell 的线程代号』,亦即是所谓的 PID(Process ID)。『 echo $$ 』即可!出现的数字就是你的 PID 号码。

变量键盘读取、数组与宣告: read, array, declare

read
要读取来自键盘输入的变量,就是用 read 这个指令了。这个指令最常被用在 shell script 的撰写当中,想要跟使用者对谈。

变量的有效范围

果在跑程序的时候,有父程序与子程序的不同程序关系时,则『变量』可否被引用与 export 有关。被 export 后的变量,我们可以称他为『环境变量』! 环境变量可以被子程序所引用,但是其他的自定义变量内容就不会存在于子程序中。

基本上你可以这样看待:

环境变量=全局变量
自定义变数=局部变量

1、当启动一个 shell,操作系统会分配一记忆区块给 shell 使用,此内存内之变量可让子程序取用
2、若在父程序利用 export 功能,可以让自定义变量的内容写到上述的记忆区块当中(环境变量);
3、当加载另一个 shell 时 (亦即启动子程序,而离开原本的父程序了),子 shell 可以将父 shell 的环境变量所在的记忆区块导入自己的环境变量区块当中。

declare / typeset
变量类型默认为『字符串』,所以若不指定变量类型,则 1+2 为一个『字符串』而不是『计算式』。 所以上述第一个执行的结果才会出现那个情况的;

bash 环境中的数值运算,预设最多仅能到达整数形态,所以 1/3 结果是 0;

数组 (array) 变量类型
image.png
与文件系统及程序的限制关系: ulimit

想象一个状况:我的 Linux 主机里面同时登入了十个人,这十个人不知怎么搞的, 同时开启了 100个文件,每个文件的大小约 10MBytes ,请问一下, 我的 Linux 主机的内存要有多大才够?10*100*10 = 10000 MBytes = 10GBytes ... 老天爷,这样,系统不挂点才有鬼哩!为了要预防这个情况的发生,所以我们的 bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等。如何设定?用 ulimit 吧!

变量内容的删除、取代与替换 (Optional)

删除
1、从前面开始删除变量内容

echo ${path#/*:}

echo ${path##/*:}
image.png
# :符合取代文字的『最短的』那一个;
##:符合取代文字的『最长的』那一个

2、从后面向前删除变量内容
上面谈到的是『从前面开始删除变量内容』,那么如果想要『从后面向前删除变量内容』呢? 这个时候就得使用百分比 (%) 符号了!

echo ${path%:*bin}

echo ${path%%:*bin}

至于 %与 %% 的意义其实与 # 及 ## 类似!

取代

将 path 的变量内容内的第一个 sbin 取代成大写 SBIN:
指令:echo ${path/sbin/SBIN}
结果:/usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 这个部分就容易理解的多了!关键词在于那两个斜线,两斜线中间的是旧字符串
# 后面的是新字符串,所以结果就会出现如上述的特殊字体部分啰!

如果是两条斜线,那么就变成所有符合的内容都会被取代喔!
echo ${path//sbin/SBIN
image.png

内容替换

image.png

命令别名与历史命令

命令别名设定: alias, unalias
alias lm='ls -al | more'

这个指令名称为 lm ,且其实他是执行 ls -al | more !不过, 要注意的是:『alias 的定义规则与变量定义规则几乎相同』, 所以你只要在 alias 后面加上你的 {『别名』='指令 选项...' }, 以后你只要输入 lm 就相当于输入了 ls -al|more 这一串指,至于如果要取消命令别名的话,那么就使用 unalias 吧

unalias lm

那么命令别名与变量有什么不同呢?命令别名是『新创一个新的指令, 你可以直接下达该指令』的,至于变量则需要使用类似『 echo 』指令才能够呼叫出变量的内容!

Bash Shell 的操作环境:

路径与指令搜寻顺序

系统里面其实有不少的 ls 指令,或者是包括内建的 echo 指令,那么来想一想,如果一个指令 (例如 ls) 被下达时, 到底是哪一个 ls 被拿来运作?很有趣吧!基本上,指令运作的顺序可以这样看:

以相对/绝对路径执行指令,例如『 /bin/ls 』或『 ./ls 』;

  1. 由 alias 找到该指令来执行;
  2. 由 bash 内建的 (builtin) 指令来执行;
  3. 透过 $PATH 这个变量的顺序搜寻到的第一个指令来执行。

举例来说,你可以下达 /bin/ls 及单纯的 ls 看看,会发现使用 ls 有颜色但是 /bin/ls 则没有颜色。因为 /bin/ls 是直接取用该指令来下达,而 ls 会因为『 alias ls='ls --color=auto' 』这个命令别名而先使用!

路径与指令搜寻顺序为:先 alias 再 builtin 再由 $PATH 找到

bash 的环境配置文件

你是否会觉得奇怪,怎么我们什么动作都没有进行,但是一进入 bash 就取得一堆有用的变量了? 这是因为系统有一些环境配置文件案的存在,让 bash 在启动时直接读取这些配置文件,以规划好 bash的操作环境啦! 而这些配置文件又可以分为全体系统的配置文件以及用户个人偏好配置文件。要注意的是, 我们自定义的命令别名啦、变数,在你注销 bash 后就会失效,所以你想要保留你的设定, 就得要将这些设定写入配置文件才行。

login 与 non-login shel
login shell:取得 bash 时需要完整的登入流程的,就称为 login shell。举例来说,你要由 tty1 ~ tty6 登入,需要输入用户的账号与密码,此时取得的 bash 就称为『 login shell 』;

non-login shell:取得 bash 接口的方法不需要重复登入的举动,举例来说,(1)你以 X window 登入 Linux 后,再以 X 的图形化接口启动终端机,此时那个终端接口并没有需要再次的输入账号与密码,那个 bash 的环境就称为 non-login shell 了。(2)你在原本的 bash 环境下再次下达 bash 这个指令,同样的也没有输入账号密码, 那第二个 bash (子程序) 也是 non-login shell 。

一般来说,login shell 其实只会读取这两个配置文件:

  1. /etc/profile:这是系统整体的设定,你最好不要修改这个文件;
  2. ~/.bash_profile 或 ~/.bash_login 或 ~/.profile:属于使用者个人设定,你要改自己的数据,就写入这里!

bash 的 login shell 情况下所读取的整体环境配置文件其实只有 /etc/profile,但是/etc/profile 还会呼叫出其他的配置文件

整个 login shell 的读取流程:


image.png
source :读入环境配置文件的指令

由于 /etc/profile 与 ~/.bash_profile 都是在取得 login shell 的时候才会读取的配置文件,所以, 如果你将自己的偏好设定写入上述的文件后,通常都是得注销再登入后,该设定才会生效。那么,能不能直接读取配置文件而不注销登入呢? 可以的!那就得要利用 source 这个指令了!


image.png

利用 source 或小数点 (.) 都可以将配置文件的内容读进来目前的 shell 环境中!举例来说,我修改了 ~/.bashrc ,那么不需要注销,立即以 source ~/.bashrc 就可以将刚刚最新设定的内容读进来目前的环境中!

通配符与特殊符号

在 bash 的操作环境中还有一个非常有用的功能,那就是通配符 (wildcard) ! 我们利用 bash 处理数据就更方便了!底下我们列出一些常用的通配符:


image.png

除了通配符之外,bash 环境中的特殊符号有哪些呢?底下我们先汇整一下:


image.png

数据流重导向

standard output 与 standard error output

简单的说,标准输出指的是『指令执行所回传的正确的讯息』,而标准错误输出可理解为『 指令执行失败后,所回传的错误讯息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无/etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个指令时,cat 会进行:
1、标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
2、标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误讯息

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!那能不能透过某些机制将这两股数据分开呢? 当然可以啊!那就是数据流重导向的功能啊!数据流重导向可以将 standard output(简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:

  1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
  2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
  3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

文件的建立方式是:
1、 该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他建立起来,但是
2、 当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
3、 也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉啰!

1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;

/dev/null 垃圾桶黑洞装置与特殊写法

如果我知道错误讯息会发生,所以要将错误讯息忽略掉而不显示或储存呢? 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!将上述的范例修订一下:

指令:find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc <==只有 stdout 会显示到屏幕上, std

如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 我们同样用底下的案例来说明:(将 2> 转到 1> 去,也可以将 1 > 转到 2 > 去)

image.png

上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。 至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &>

standard input : < 与 <<

< 是『将原本需要由键盘输入的数据,改由文件内容来取代』的意思:

image.png

由于加入 > 在 cat 后,所以那个 catfile 会被主动的建立,而内容就是刚刚键盘上面输入的那两行数据。那我能不能用纯文本文件取代键盘的输入,也就是说,用某个文件的内容来取代键盘
的敲击呢? 可以的!如下所示:


image.png

理解 < 之后,再来则是怪可怕一把的 << 这个连续两个小于的符号了。 他代表的是『结束的输入字符』的意思!举例来讲:『我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束』,那我可以这样做:

image.png

利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束!

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

1、cmd ; cmd (不考虑指令相关性的连续指令下达)

2、$? (指令回传值) 与 && 或 ||
透过这个回传值来判断后续的指令是否要执行!这就得要藉由『 && 』及『 || 』的帮忙了! 注意,两个 & 之间是没有空格的!那个 | 则是 [Shift]+[] 的按键结果。

image.png

示例:我不清楚 /tmp/abc 是否存在,但就是要建立 /tmp/abc/hehe 文件

 ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe

上面这个范例三总是会尝试建立 /tmp/abc/hehe 的喔!不论 /tmp/abc 是否存在。那么范例三应该如何解释呢? 由于 Linux 底下的指令都是由左往右执行的,所以范例三有几种结果我们来分析一下:

(1)若 /tmp/abc 不存在故回传 $?≠0,则 (2)因为 || 遇到非为 0 的 $? 故开始 mkdir /tmp/abc,由于 mkdir/tmp/abc 会成功进行,所以回传 $?=0 (3)因为 && 遇到 $?=0 故会执行 touch /tmp/abc/hehe,最终 hehe 就被建立了;

(2)若 /tmp/abc 存在故回传 $?=0,则 (2)因为 || 遇到 0 的 $? 不会进行,此时 $?=0 继续向后传,故 (3)因为 && 遇到 $?=0 就开始建立 /tmp/abc/hehe 了!最终 /tmp/abc/hehe 被建立起

整个流程图示如下:


image.png

由于指令是一个接着一个去执行的,因此,如果真要使用判断,那么这个 && 与 || 的顺序就不能搞错。

管线命令 (pipe)

bash 命令执行的时候有输出的数据会出现! 那么如果这群数据必需要经过几道手续之后才能得到我们所想要的格式,应该如何来设定? 这就牵涉到管线命令的问题了 (pipe) ,管线命令使用的是『 | 』这个界定符号! 另外,管线命令与『连续下达命令』是不一样的

管线命令『 | 』仅能处理经由前面一个指令传来的正确信息,也就是 standard output 的信息,对于stdandard error 并没有直接处理的能力。那么整体的管线命令可以使用下图表示:


image.png

在每个管线后面接的第一个数据必定是『指令』!而且这个指令必须要能够接受 standard input 的数据才行,这样的指令才可以是为『管线命令』,例如 less, more, head, tail 等都是可以接受 standard input 的管线命令啦。至于例如 ls, cp, mv 等就不是管线命令了!因为 ls, cp, mv 并不会接受来自 stdin 的数据。 也就是说,管线命令主要有两个比较需要注意的地方:
1、管线命令仅会处理 standard output,对于 standard error output 会予以忽略
2、管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行

总结:

1、由于核心在内存中是受保护的区块,因此我们必须要透过『 Shell 』将我们输入的指令与 Kernel 沟通,好让 Kernel 可以控制硬件来正确无误的工作

2、学习 shell 的原因主要有:文字接口的 shell 在各大 distribution 都一样;远程管理时文字接口速度较快;shell 是管理 Linux 系统非常重要的一环,因为 Linux 内很多控制都是以 shell 撰写的。

3、系统合法的 shell 均写在 /etc/shells 文件中;

4、用户默认登入取得的 shell 记录于 /etc/passwd 的最后一个字段;

5、bash 的功能主要有:命令编修能力;命令与文件补全功能;命令别名设定功能;工作控制、前景背景控制;程序化脚本;通配符

6、type 可以用来找到执行指令为何种类型,亦可用于与 which 相同的功能;

7、变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据

8、变量主要有环境变量与自定义变量,或称为全局变量与局部变量

9、使用 env 与 export 可观察环境变量,其中 export 可以将自定义变量转成环境变量;

10、set 可以观察目前 bash 环境下的所有变量;

11、$? 亦为变量,是前一个指令执行完毕后的回传值。在 Linux 回传值为 0 代表执行成功;

12、locale 可用于观察语系资料;

13、可用 read 让用户由键盘输入变量的值

14、ulimit 可用以限制用户使用系统的资源情况

15、bash 的配置文件主要分为 login shell 与 non-login shell。login shell 主要读取 /etc/profile 与 ~/.bash_profile,non-login shell 则仅读取 ~/.bashrc

16、在使用 vim 时,若不小心按了 [crtl]+s 则画面会被冻结。你可以使用 [ctrl]+q 来解除冻结

17、通配符主要有: *, ?, [] 等等

18、数据流重导向透过 >, 2>, < 之类的符号将输出的信息转到其他文件或装置去;

19、连续命令的下达可透过 ; && || 等符号来处理

20、管线命令的重点是:『管线命令仅会处理 standard output,对于 standard error output 会予以忽略』 『管线命令必须要能够接受来自前一个指令的数据成为 standard input 继续处理才行。』

21、本章介绍的管线命令主要有:cut, grep, sort, wc, uniq, tee, tr, col, join, paste, expand, split, xargs 等。

你可能感兴趣的:(Linux基础篇-第十章-BASH 这个 Shell)