第5章Linux的vim 与Bash 学习目标 (1)掌握vim编辑器的功能。 (2)了解BashShel 的基本功能。 (3)理解Bash环境变量。 vim和Bash是进行ShelScript编写的基础,也是Linux系统编程比较重要的先导 内容。本章首先讲解Linux下vim编辑器的功能和使用,然后介绍Shel 与Bash之间的 关系,以及Shel 的相关内容和命令,接着详细讲解Bash的基本功能和环境变量的使用, 从而为Shel 编程打下坚实的基础。 5.1 vim 编辑器 每个系统管理员都应该至少要学会一种文字接口的编辑处理器,以方便系统日常 的管理行为。在Linux上的文字处理软件非常多,vi与vim编辑器是所有UNIX及 Linux系统下标准的编辑器,相当于Windows系统中的记事本,它的强大不逊色于任何 最新的文本编辑器,是人们使用Linux系统不能缺少的工具。对UNIX及Linux系统 的任何版本,vi编辑器都是完全相同的。所以vi编辑器是未来人们进行ShelScript程 序的编写与服务器相关配置文件的首选编辑工具,学会使用它后,将在Linux的世界里 畅行无阻。 5.1.1 vi、vim 与gvim 诞生于20世纪70年代的vi编辑器是所有的类UNIX系统默认的文本编辑器,所以 所有的类UNIX系统都会内置vi编辑器,其他的编辑器则不一定会存在。但是目前人们 使用比较多的是vim编辑器。vim具有程序编辑的能力,可以主动地以字体颜色辨别语 法的正确性,方便程序设计。 vim是从vi发展出来的一个文本编辑器,不过在vi的基础上增加了很多新的特性, vim普遍被推崇为类vi编辑器中最好的一个,其代码补完、编译及错误跳转等方便编程 的功能特别丰富,在程序员中被广泛使用,和Emacs并列成为类UNIX系统用户最喜欢 的编辑器。vim的第一个版本由BramMoolenar在1991年发布,最初的简称是Vi IMitation,随着功能的不断增加,正式名称改成了ViIMproved。 147 gvim 的g指的是GUI,也就是图形化界面,相当于在vim 包了一层图形化界面。所 以可以说gvim 是vim 的图形前端,一般运行在桌面环境中,而vim 一般运行在命令行 下。相比之下,gvim 拥有更丰富的颜色和字体,还有菜单和滚动条,以及更友好的鼠标操 作等,除此之外与vim 差异不大。gvim 是跨平台的编辑器,主流的Linux操作系统上面 都有它的版本,并会根据安装的平台自动选择相应语言包,支持中文及其各种编码,这个 极具UNIX特色和风格(simpleisthebest)的编辑器相信会带来不同的感受。 ...................... ........ ...................... .......... .. .. .. 操作演示 vim 和gvim 的 安装 5.1.2 vim 和gvim 的安装 目前Fedora29 默认只安装了vi命令,可以直接运行 vim 由系统自动帮忙完成这个命令的安装,当然也可以通过 #dnf-yinstallvim-enhanced完成vim 命令所属rpm 包的安装。 [root@localhost ~]#vim bash: vim: 未找到命令… 安装软件包vim-enhanced 以提供命令vim? [N/y]y * 正在队列中等待… * 装入软件包列表… 下列软件包必须安装: gpm-libs-1.20.7-16.fc29.x86_64 Dynamic library for for the gpm vim-common-2:8.1.1991-2.fc29.x86_64 The common files needed by any version of the VIM editor vim-enhanced- 2:8.1.1991- 2.fc29.x86_64 A version of the VIM editor which includes recent enhancements vim-filesystem-2:8.1.1991-2.fc29.noarch VIM filesystem layout 继续更改? [N/y] y …* 正在安装软件包… 而gvim 可以采用dnf命令(参见8.3节)完成安装,安装完成后,输入命令gvim,运行 界面如图5.1所示,可以很方便地使用鼠标进行界面操作和内容编辑。 [root@localhost ~]#gvim bash: gvim: 未找到命令… 相似命令是: 'vim' [root@localhost ~]#dnf -y install vim-X11 …v im-X11 x86_64 2:8.1.1991-2.fc29 updates 1.5 M …安装 1 软件包 148 总下载:1.5 M …已 安装: vim-X11-2:8.1.1991-2.fc29.x86_64 完毕! 图5.1 gvim 界面 5.1.3 vi/vim 的使用 如图5.2所示,基本上vim 可以分为三种模式状态,分别是命令模式、输入模式和底 ...................... ........ ...................... .......... .. .. .. 操作演示 vim 的使用 线命令模式,各模式的功能区分如下。 1.命令模式 以vim打开一个文件就直接进入命令模式(这是默认的模 式)。在这个模式中,可以使用上、下、左、右按键来移动光标, 可以使用删除字符或删除整行来处理文件内容,也可以使用复制、粘贴来处理文件的数据。 2.输入模式 在命令模式中可以进行删除、复制、粘贴等操作,但是却无法编辑文件的内容,当按下 149 图5.2 vi/vim 工作模式 i、I、o、O、a、A、r、R 等任何一个字母之后进入输入模式。这时候屏幕的左下方会出现 INSERT或REPLACE的字样,此时才可以进行编辑。而如果要回到命令模式时,则必 须要按下Esc键即可退出输入模式。 3.底线命令模式 输入“:、/、?”三个中的任何一个,都可以将光标移动到最底下那一行。在这个模式 中,可以提供查找、读取、存盘、替换字符、离开vi、显示行号等功能。 使用vim 建立一个文件的一般步骤如下。 (1)输入“vim 文件名”,进入vim 的命令模式,可以在左下角观察到这个文件目前的 状态,如下所示,watch.txt此时是一个新文件。 [root@localhost ~]#vim watch.txt ~~~ "watch.txt" [新文件] 0,0-1 全部 (2)按下i(o或a)键之后,则进入输入模式,左下角出现“插入”,则可以开始编辑文 字,可以输入任意字符。 (3)按下Esc键可再次回到命令模式,此时“插入”已不再出现,内容编辑完毕。在命 令模式下,vim 提供了文本整行的删除(dd)、复制(yy)与粘贴(p),用法相同。以dd为例, 可以输入dd:连续按d键两次,删除当前行;也可以输入dnd:如连续按d、3、d,删除包括 当前行在内的往下三行。 (4)然后按下“:”键进入底线命令模式,可以输入wq保存退出。vim 退出编辑器的 相关方式如下。 :w表示将缓冲区写入文件,即保存修改,但不退出。 :wq表示保存修改并退出。 :x表示保存修改并退出。 :q表示退出,如果对缓冲区进行过修改,则会提示。 150 :q! 表示强制退出,放弃修改。 hello world! I will study Linux ~~~ :wq vim 还有很多实用的功能,大家可以在使用过程中查阅vim 的官方网站(http:// www.vim.org)加强对vim 的深入了解。例如要想在vim 中显示文件内容的行号有两种 方式。 (1)用vim 打开文件时,按Esc键进入命令模式,输入setnu,即可显示行号。 (2)直接修改配置文件,#vim ~/.vimrc(注:.vimrc文件原先可能没有,在此可以 创建),在该文件中添加一行setnu,然后保存,退出。 5.2 Shell与Bash Shell是Linux系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接 图5.3 Linux结构示意图 收用户输入的命令并把它送入内核去执行。Shell的 英文意思是外壳,在Linux系统,Shell实际上也是一 个程序,它是用户和操作系统间的命令解释器,负责 接收用户输入的命令并将它翻译成操作系统能够理 解的指令。如果把Linux内核想象成一个球体的中 心,Shell就是围绕内核的外层,从Shell向Linux操 作系统传递命令时,内核就会做出相应的反应,如图 5.3所示。例如,用户输入ls-l,Shell首先翻译这条 命令;然后判断该命令是内部命令还是一个应用程 序,Shell的内部命令或应用程序将被分解为系统调 用并传给Linux内核执行翻译后的指令;最后Linux 内核将指令的执行结果返回给Shell。 因为Linux就是以Bash为预设Shell的,在Linux下如果不懂Bash,其他的内容就 没有意义了,因为许多命令的执行是通过Bash的环境来处理的。 Bash(GNUBourne-AgainShell)是许多Linux平台的内定Shell,事实上,还有许多 传统UNIX上用的Shell,如tcsh、csh、ash、bsh、ksh等,ShellScript大致都类同,当学会 一种Shell以后,其他的Shell会很快就上手。多数情况下一个ShellScript通常可以在 很多种Shell上使用。Bash是大多数Linux系统以及MacOSXv10.4默认的Shell,它能 运行于大多数UNIX 风格的操作系统之上,甚至被移植到了MicrosoftWindows上的 Cygwin系统中,以实现Windows的POSIX虚拟接口。 151 5.3 Bash的基本功能 Bash是当前Linux版本的标准Shell。Bash与BourneShell完全向后兼容,并且在 BourneShell的基础上增加和增强了很多特性。Bash 也包含了很多csh 和ksh 里的优 点。Bash有很灵活和强大的编程接口,同时又有很友好的用户界面。Bash的主要优点 是它有命令记忆功能,即历史命令history,记录在/home/用户名/.bash_history中,它还 有命令补全功能,能够设置别名,能够随时结束终端进程,可以编写脚本程序,还有通配符 能够帮助用户查询和命令执行。 5.3.1 解析命令行 ...................... ........ ...................... .......... .. .. .. 操作演示 解析命令行 当用户打开一个(虚拟)终端时,可以看到一个Shell提 示符,标识了命令行的开始。用户可以在提示符后面输入任 何命令及其选项与参数。请注意在命令行中选项先于参数 输入。 #command [选项][参数] [root@localhost ~]#ls -l /root 总用量116 … 在一个命令行中可以输入多个命令,用分号将多个命令隔开。 [root@localhost ~]#touch mydata [root@localhost ~]#cp /proc/cpuinfo cpuinfo ; ls -a … 如果一个命令太长,无法在一行中显示,可以使用反斜线来续行,在多个命令行上输 入一个命令或多个命令。 [root@localhost ~]#cp /proc/cpuinfo cpuinfo ;\ >ls -a … 查询某命令是否为Bash内部命令:#type-t命令名,其中file为外部命令;alias为 命令别名;builtin为内部命令。 [root@localhost ~]#type -t ll alias [root@localhost ~]#type -t cd 152 builtin [root@localhost ~]#type -t mkdir file ...................... ........ ...................... .......... .. .. .. 操作演示 通配符的使用 5.3.2 通配符 通配符是一种特殊符号,可以用来在引用文件名时简化 命令的书写。在Bash中可以使用三种通配符:*、?、[],用 来模糊搜索文件。通配符的含义如表5.1所示。 表5.1 通配符的含义 符号含 义 * 任意的字符串(包括零个字符) ? 匹配任何单个字符 [] 创建一个字符列表,方括号中的字符用来匹配或不匹配单个字符。如 [xyz]匹配x、y或z,但不能匹配xx、xy或者其他任意组合。 无论列表中有多少个字符,它只匹配一个字符。 [abcde]可以简写为[a-e]。 另外,用感叹号作为列表的第一个字符可以起到反意作用,如 [!xyz]表示匹配x、y、z以外的任意一个字符 通配符的举例如下。 通配符*的常用方法就是查找具有相同扩展名的文件,例如,ls*.tgz就是显示当前 目录下后缀名为tgz的所有文件。 [root@localhost ~]#touch sun.tgz [root@localhost ~]#touch sky.tgz [root@localhost ~]#ls *.tgz sky.tgz sun.tgz 通配符*有时可以将几百条命令缩短成一个命令。例如,rm-f*.jpg就是删除当前 目录下后缀名为jpg的所有文件。 问号通配符? 必须匹配一个且只能匹配一个字符,通常用来查找比* 更为精确的 匹配。 [root@localhost ~]#ls *.? ? ? anaconda-ks.cfg hjk.dat install.log test.txt tst.txt watch.txt //显示文件后缀名只有三个字符的所有文件 方括号通配符使用括号内的字符作为被匹配的字符,且只能匹配其中的一个字符。 如列出以a、b、c开头,且以dat为扩展名的所有文件:ls [abc]*.dat。也可以在方括号 153 中使用连字符-来指定一个范围,如列出以字母开头、数字结尾的所有文件:#ls [a-zAZ]*[ 0-9]。 ...................... ........ ...................... .......... .. .. .. 操作演示 命令别名 5.3.3 命令别名 别名是Bash中用来节省时间的另一项重要功能,直接运 行alias命令显示所有当前的别名,会发现其实rm 别名也是 rm-i。要特别注意的是,别名既可以生造一个单词,也可以覆盖一个已有命令。 [root@localhost ~]#alias alias cp='cp -i' alias grep='grep --color=auto' alias l.='ls -d .* --color=auto' alias ll='ls -l --color=auto' alias ls='ls --color=auto' alias mv='mv -i' alias rm='rm -i' alias which='alias | /usr/bin/which -- tty- only - - read- alias - - show- dot - - show-tilde' Bash允许用户按照自己喜欢的方式通过alias对相关的命令进行自定义创建;也可 以通过unalias命令取消已创建的别名。 [root@localhost ~]#alias lm='ls' [root@localhost ~]#lm anaconda-ks.cfg install.log.syslog newdata test.txt 公共的图片音乐 hjk.dat list sky.tar.qz tst.txt 模板文件桌面 install.log mydata sun.tar.qz watch.txt 视频下载 [root@localhost ~]#ls anaconda-ks.cfg install.log.syslog newdata test.txt 公共的图片音乐 hjk.dat list sky.tar.qz tst.txt 模板文件桌面 install.log mydata sun.tar.qz watch.txt 视频下载 [root@localhost ~]#unalias lm [root@localhost ~]#lm 命令未找到。 5.3.4 命令行自动补齐 通常用户在Bash下输入命令时不必把命令输全,Shell就能判断出所需要的命令。 154 该功能的核心思想:Bash根据用户已输入的信息来查找以这些信息开头的命令,从而试 图完成当前命令的输入工作。 用来执行这项功能的键是Tab键,按下Tab键后,Bash就试图完成整个命令的输入,并 将列出所有能够与当前输入字符相匹配的命令列表。例如在命令行输入his, Bash就会自动将命令补全为查看用户历史命令为history。这项功能同样适用于文件名 的自动补齐,例如要进入目录:/etc/sysconfig/network-scripts/,不需要一个一个字符的 输入,既浪费时间,又可能输错,可以直接输入如下命令。 [root@localhost ~]#cd /esyscne- [root@localhost network-scripts]#pwd /etc/sysconfig/network-scripts/ 5.3.5 管道与awk、cut命令 管道是Linux从UNIX继承过来的进程间的通信机制,是把一个程序的输出直接连 ...................... ........ ...................... .......... .. .. .. 操作演示 管道的使用 接到另一个程序的输入。管道是UNIX 早期的一个重要通 信方法,其思想是在内存中创建一个共享文件,从而使通信双 方利用这个共享文件来传递信息。由于这种方式具有单向传 递数据的特点,所以这个作为传递消息的共享文件就叫作 “管道”。 我们在第三章介绍head、tail命令以及grep命令时已经使用了管道,下面先回顾一 下这几个命令与管道的结合使用。 [root@localhost ~]#head -n 20 /etc/passwd | tail -n 10 operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin avahi - autoipd: x: 170: 170: Avahi IPv4LL Stack:/var/lib/avahi - autoipd:/ sbin/nologin usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin /*该命令用到了管道文件,即先获取passwd 文件的前20 行内容,但是不直接打印而是把这个 结果作为管道后面命令tail 的输入,从而使得tail 命令在这20 行内容的基础上截取获得后 10 行*/ 155 [root@localhost ~]#cat /proc/meminfo | grep Total MemTotal: 2016276 kB SwapTotal: 2097148 kB VmallocTotal: 34359738367 kB CmaTotal: 0 kB HugePages_Total: 0 [root@localhost ~]#cat /proc/meminfo | grep Mem MemTotal: 2016276 kB MemFree: 381308 kB MemAvailable: 922540 kB [root@localhost ~]#cat /proc/meminfo | grep Total | grep Mem MemTotal: 2016276 kB //连续用到了两个管道,先过滤出含有Total 内容的5 行,在此基础上再次过滤含有Mem 内容 的3 行 下面结合经常与管道一起使用的awk命令和cut命令进一步深入理解管道。 1.awk命令 awk是一个强大的文本分析工具,相对于grep的查找,awk在其对数据分析并生成 报告时,显得尤为强大。简单来说,awk就是把文件逐行读入,以空格为默认分隔符将每 行切片,切开的部分再进行各种分析处理。 awk有3个不同版本:awk、nawk和gawk,如果没有特别说明,一般指gawk,gawk 是awk的GNU 版本。awk其名称得自于它的创始人AlfredAho、PeterWeinberger和 BrianKernighan姓氏的首个字母。实际上awk的确拥有自己的语言:awk程序设计语 言,三位创建者已将它正式定义为“样式扫描和处理语言”。它允许创建简短的程序,这些 程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他 的功能。 awk命令的基本语法如下。 awk [选项][脚本]文件名 在默认情况下,awk会将如下变量分配给它在文本行中发现的数据字段。 $0:代表整个文本行。 $1:代表文本行中的第1个数据字段。 $2:代表文本行中的第2个数据字段。 $n:代表文本行中的第n 个数据字段。 前面说过,在awk中,默认的字段分隔符是任意的空白字符(例如空格或制表符)。 在文本行中,每个数据字段都是通过字段分隔符划分的。awk在读取一行文本时,会用预 定义的字段分隔符划分每个数据字段。