权限、进程、环境以及 VI
权限
传统的 UNIX 操作系统与那些传统的 MS-DOS 操作系统不同,区别在于它们不仅是多重任务处理系统,还是多用户系统。
这意味着同一时间内可以有多个用户使用同一台计算机,虽然一套标准的计算机可能只包含一个键盘和一台显示器,但是它仍然可以同时被一个以上的用户使用。如果计算机连接到一个网络或互联网中,远程用户可以通过 ssh 登录并操作这台计算机。
所有者、组成员和其他所有用户
在 UNIX 安全模型中,一个用户可以拥有 own
文件和目录。当一个用户拥有一个文件或目录时,它将对该文件或目录的访问权限拥有控制权。反过来,用户又归属于一个群组 group
,该群组有一个或多个用户组成,组中用户对文件和目录的访问权限由其所有者授予。除了可以搜娱群组访问权限之外,文件所有者也可以授予所有用户一些访问权限。使用 id
命令可以获得用户身份标识的相关信息。
id
=> uid=500(me) gid=500(me) groups=500(me)
查看 id
命令的输出结果。在创建用户账户的时候,用户将被分配一个称为用户 ID 或 uid
的号码。为了符合人们的使用习惯,用户 ID 与用户名一一映射。同时用户将被分配一个有效组 ID 或被称为 gid
而且该用户也可归属于其他群组。
前面的结果在 Fedora
系统中,在其它系统中输出结果可能有点不同。
读取、写入和执行
对文件和目录的访问权限是按照读访问、写访问以及执行访问来定义的。
当我们查看 ls
命令的输出结果时,可以得到一些线索
ls -l foo.txt
=> -rw-rw-r-- 1 me me 0 2012-03-03-06 14:52 foo.txt
列在输出结果的前 10 个字符表示的是文件属性。
-
文件类型rw-
所有者权限rw-
组权限r--
其他用户权限
文件类型
-
普通文件d
目录文件l
符号链接c
字符设备文件,表示以字节流形式处理数据的设备,如终端或调制解调器b
块设备文件,表示以数据块方式处理数据的文件
文件属性中剩下的九个字符成为文件模式,分别表示文件所有者、文件所属群组以及其他所有用户对该文件的读取、写入和执行权限。
分别设置 r
、 w
和 x
的模式属性将会对文件和目录带来不同的影响
r
文件允许打开和读取文件,目录如果设置了执行权限,那么允许列出目录内容w
文件允许写入或阶段文件,如果也设置了执行权限,那么目录中的文件允许被创建、被删除和被重命名,目录该权限不允许重命名或删除文件。是否能重命名和删除文件由目录权限决定x
允许把文件当作程序来执行。用脚本写的程序文件必须被设置为刻度
下面是一个文件属性设置的例子
chmod——更改文件模式
我们可以使用 chmod
命令来更改文件或目录到模式(权限)。需要注意的是只有文件所有者和超级用户才可以更改文件或目录的模式。 chmod
命令支持两种不同的改变文件模式的方式——八进制数字表示法和符号表示法。
八进制表示法是指使用八进制数字来设置所期望的权限模式。
八进制 | 二进制 | 文件模式 |
---|---|---|
0 | 000 | --- |
1 | 001 | --x |
2 | 010 | -w- |
3 | 011 | -wx |
4 | 100 | r-- |
5 | 101 | r-x |
6 | 110 | rw- |
7 | 111 | rwx |
通过使用3位八进制数字,我们可以设置文件所有者、组成员和其他所有用户的文件模式
chmod 600 foo.txt
上面命令设置文件所有者具有读写权限,取消组用户和其他所有用户的所有权限。其实常用的也就7、6、5、4、0
符号表示法
chmod
命令支持一种符号表示法来指定文件模式。该符号表示法分为三部分:更改会影响谁、要执行那个操作以及要设置那种权限
u
,user
的简写,表示文件或目录的所有者g
文件所属群组o
,others
的简写,表示其他所有用户a
,all
的简写,是u
,g
和o
三者的组合
如果没有指定字符,则假定使用 all
。操作符 +
表示增加一种权限, -
表示删除一种权限, =
表示只有指定的权限可用,其他所有权限被删除
权限由字符 r
, w
和 x
来指定
u+x
为文件所有者添加可执行权限u-x
删除文件所有者的可执行权限+x
为文件所有者、所属群组和其他所有用户添加可执行权限,等价于a+x
- ...
符号表示法的优点在于允许设置单个属性而不影响其他任何属性
通过GUI设置文件模式
右击文件或目录图标都会弹出一个属性对话框
umask——设置默认权限
umask
命令控制着创建文件时指定给文件的默认权限。它使用八进制表示法来表示从文件模式属性中删除一个位掩码
umask 0002
+ ls -l foo.txt
其中 0002
是文件属性,掩码的二进制数值中每个出现 1
的位置,其对应的属性都被取消。
在创建文件前使用 umask
来设置文件权限,如果不带任何参数可以直接使用 umask
来查看默认创建文件权限。
大多数情况下,你并不需要修改掩码值,默认掩码值就很好了,在一些高安全级别环境下,需要控制掩码值。
更改身份
在很多时候,我们会发现可以拥有另一个用户的身份很有必要。我们经常会需要获得超级用户的特权来执行一些管理任务,但是也可以编程另一个普通用户来执行这些任务。有三种方法来转换身份
- 注销系统并以其他用户的身份重新登录系统
- 使用
su
命令 - 使用
sudo
命令
这里第一种方法明显不如其他两种方法来得方便。在 shell 会话状态下,使用 su
命令将允许你假定为另一个用户的身份,既可以以这个用户的ID来启动一个新的shell会话,也可以以这个
用户的身份发布一个命令。使用 sudo
命令将允许管理者创建一个称为 /etc/sudoer
的配置文件,并且定义给一些特定的命令,这些命令只有被赋予为假定身份的特定用户才允许执行。
su——以其他用户和组ID的身份来运行 shell
su
命令用来以另一个用户的身份来启动 shell。该命令的一般形式如下:
su [-[l]] [user]
如果包含 -l
选项,那么得到的 shell 绘画界面僵尸用于指定用户的登录 shell 界面。这就意味着该指定用户的运行环境将被加载,而且其工作目录也将更改为该指定用户的主目录。如果没有指定用户,那么默认假定为超级用户。 -l
可以缩写为 -
,这一形式经常被使用
su -
输入 su
命令后,系统会提示输入该超级用户的密码。如果密码输入正确将会出现新的 shell 提示符,该提示符表示该 shell 将拥有超级用户的特权(提示符的末尾字符是 #
,而不是 $
),而且当前工作目录现在也是用于超级用户的主目录(通常情况下为 /root
)。在试用结束时,输入 exit
,将返回到之前的 shell 环境。
我们也可以使用 su
命令执行单个命令,而不需要开启一个新的交互式命令界面
su -c 'command'
是哟个这种格式,单个命令行将被传递到一个新的 shell 环境下执行。这里需要用单引号把命令行引起来。它会在新的 shell 环境下执行
sudo——以另一个用户的身份执行命令
sudo
命令在很多方面都类似于 su
命令,管理者可以通过配置 sudo
命令,使系统以一种可控的方式,允许一个普通用户以一个不同的用户身份执行命令。使用 sudo
命令时,用户只需要输入自己的密码来进行认证。
一旦认证通过,指定的命令就将被执行。 su
命令和 sudo
命令的一个重要区别在于 sudo
命令并不需要启动一个新的 shell 环境,所以使用 shell 命令时不需要使用单引号。
想知道 sudo
命令可以授予哪些权限,可以使用 -l
来查看
sudo -l
在第一次使用了 sudo
命令之后,系统会信任用户几分钟,此时可以不用输入 sudo
命令操作
chown——更改文件所有者和所属群组
这个命令需要超级用户的权限。格式如下:
chown [ower][:[group]] file ...
chown
命令更改的是文件所有者还是文件所属群组,或者对两者都更改取决于该命令的第一个参数
参数 | 结果 |
---|---|
bob | 把文件所有者从当前所有者改为用户 bob |
bob:users | 把文件所有者从当前所有者改为用户bob,并且把文件所属群组改为 users 群组 |
:admins | 把文件所属群组改为 admins 组,文件所有者不变 |
bob: | 把文件所有者从当前所有者改为用户bob,并且把文件所属群组改为 bob 登陆系统所属的组 |
chgrp——更改文件所属群组
该命令除了限制多一点之外,和 chown
命令的使用方式几乎相同
进程
现代操作系统通常都支持多任务处理。多重任务处理是指系统通过快速切换运行中的程序来实现多任务的同时执行。Linux 内核通过使用进程来管理多重任务。
有时计算机运行速度会变得很慢,此时可以使用命令行来查看程序当前运行情况以及终止运行异常的进程的一些工具
进程如何工作
系统启动时,内核先把它的一些程序初始化为进程,然后运行一个称为 init
的程序。此程序将依次运行一系列称为脚本初始化的 shell 脚本,这些脚本将会启动所有系统服务。其中很多服务都是通过守护程序来实现。而后台程序只是呆在后台做它们自己的事。
一个程序的运行可以触发其他程序的运行,在进程系统中这种情况被表述为父进程创建子进程。
内核会保存每个进程的信息以便确保任务有序进行。比如每个进程将被分配一个称为进程ID的号码。进程ID是按递增的顺序来分配, init
进程的PID始终为 ·。和文件系统类似,进程·系统中也存在所有者、用户ID、有效用户ID等。
使用ps命令查看进程信息
最简单的格式如下
ps
返回的数据格式中, TTY
代表了进程的控制终端。 TIME
字段表示了进程消耗的CPU时间总和。
如果在 ps
命令后面添加一个选项,我们将得到更大的视图界面
ps x
它将告知 ps
命令的所有进程,而不需要关注它们是由哪个总段所控制的, TTY
中的 ?
表示没有控制终端,把 ps
命令作为 less
命令的输入方法通常横贯用,它可以更方便地查看显示结果。输出结果中添加了一个命名为 STAT
的新列。它是 state
的缩写,显示的是进程的当前状态。
状态 | 含义 |
---|---|
R | 运行状态。进程正在进行或准备进行 |
S | 睡眠状态。进程不再运行,而是在等待某个事件发生,如键盘输入或收到网络报文 |
D | 不可中断的睡眠状态。进程在等待I/O操作,如硬盘驱动 |
T | 暂停状态。 |
Z | 无效或“僵尸”进程。子进程被终止但还没有被父进程彻底释放 |
< | 高优先级进程 |
N | 低优先级进程,只有在高优先级进程使用完处理器后才能够使用处理器的时间 |
另一个常用的选项组合是 aux
,它将输出更多的信息,它会显示属于每个用户的进程信息,使用这些选项时不带前置连字符将使得命令以 BSD 模式
运行。具体的列信息如下。
标题 | 含义 |
---|---|
USER | 用户ID。表示该进程所有者 |
%CPU | CPU 使用百分比 |
%MEM | 内存使用百分比 |
VSZ | 虚拟耗用内存大小 |
RSS | 实际使用内存大小,即物理内存大小,以KB为单位 |
START | 进程开始的时间,如果数值超过24个小时,那么将使用日期表示 |
使用 top 命令动态查看进程信息
虽然 PS
命令可以显示有关机器运行情况的很多信息,但是它提供的只是在 PS
命令被执行时刻机器状态的一个快照。要查看机器运行情况的动态视图可以使用 top
命令
top
top
程序将按照进程活动的顺序,以列表的形式持续更新显示系统进程的当前信息(每 3 秒更新一次)。它用于查看系统“最高”进程的运行情况。显示内容包括两部分上名师系统总体状态信息。下面显示的是按 cpu 活动时间排序的进程情况表。
控制进程
中断进程
ctrl + c
但不是所有命令行程序可以使用这种方法来实现中断。
使进程在后台运行
假设我们想要 shell 提示符返回,但又不终止程序,那么就可以通过让该程序在后台运行来实现。想在启动程序时在后台运行,可以在命令行后加上 &
来实现。
shell 的作业控制也提供了一种方式来查看从该终端启动的所有作业。使用 jobs
命令可以得到所有信息。
使进程回到前台运行
可以通过 fg
命令来实现。在命令后面加上百分比符号和作业编号,作业编号通过 jobs
命令获得。
fg %1
停止(暂停)进程
如果我们想暂停进程而不是终止进程,那么我们通常需要将前台运行的进程移到后台去运行。我们可以输入 ctrl + z
键。接触这种状态可以使用 fg
或 bg
来让进程在前台或后台恢复运行。
在图形化界面启动,程序会启动失败,但是在命令行启动可以查看错误信息。
信号
kill
命令通常用来“杀死”进程,它可以用来终止运行不正常的程序或反过来拒绝终止的程序
这些看起来非常容易,实际上这些命令不是杀死进程,而是给进程发送信号。比如 ctrl + c
发送一个称为 INT
(终端,Interrupt)的信号,在按下 ctrl + z
时,他将发送一个成为 TSTP
(终端暂停,Terminal Stop)的信号。
使用kill命令发送信号到进程
kill
命令常用语法格式如下
kill [-signal] PID...
如果命令行中没有指定信号,那么默认发送 TERM
信号。 kill
命令常用来发送信号如下所示
信号编号 | 信号名 | 含义 |
---|---|---|
1 | HUP | 挂起符号。该信号通过关闭终端会话的方式来表现,前台程序会被终止,后台程序会进行重新初始化,即终止并读取配置文件 |
2 | INT | 中断信号,和按下ctrl + c的效果一样 |
3 | KILL | 杀死信号,此信号不会真正的发送到目标程序,而是内核宁愿立即终止了该进程,它不会对自己进行清理或保存 |
4 | TERM | 终止信号,这是kill命令默认发送的信号类型,如果程序有足够的“活力”来接受信号,那么它将被终止 |
5 | CONT | 继续运行账号,霍夫接受了STOP信号的进程 |
6 | STOP | 暂停信号,该信号将使进程暂停,而不是终止,和KILL信号类似 |
使用killal命令发送信号给多个进程 我们可以给指定程序或指定用户名的多个进程发送信号,一般格式如下
killall [-u user] [-signal] name...
记住,和 kill
命令一样,你必须具有超级用户权限,才能够使用 killall
命令给不属于自己的进程发送信号
更多与进程相关的命令
由于进程监控是一项重要的系统管理任务,所以存在很多命令用来为它服务
命令 | 描述 |
---|---|
pstree | 以树状的模式输出进程列表,该模式显示了进程间的父/子关系 |
vmstat | 输出系统资源使用情况的快照,包括内存,交换空间和磁盘I/O,如果想要持续查看输出,可以在命令后面加上一个间隔时间(以秒为单位)动态更新显示内容 |
xload | 用来绘制显示系统时间负载情况图像的一种图形化界面程序 |
tload | 类似于xload程序,但是图形是在终端上绘制。 |
环境
在 shell 会话调用环境期间,shell 会存储大量的信息。程序使用存储在环境中的数据来确定我们的配置。
环境中存储的是什么
尽管 shell 在环境中存储了两种基本类型的数据,但是在 bash 中,这两种数据基本没有区别。这两种数据类型分别是环境变量和 shell 变量。shell 变量是由 bash 存放的少量数据,环境变量就是除此之外的所有其他变量。除变量之外,shell 还存储了一些编程数据,也就是别名和 shell 函数。
检查环境
要了解环境中存储的内容,需要用到集成在 bash 中的 set
命令或 printenv
程序。不同的是, set
命令会同时显示 shell 变量和环境变量,而 printenv
只会显示环境变量。由于环境的内容可能会比较冗长,所以最好以管道重定向到 less
命令中。
printenv | less
使用 set
命令时,如果不带选项或参数,那么只会显示 shell 变量、环境变量、以及任何已定义的 shell 函数。 set
命令的输出结果是按照字母顺序排列的。如果要查看单个变量的值,我们也可以使用 echo
命令
echo $HOME
如果想鉴别是否为别命只能使用 alias
一些有趣的变量
变量 | 说明 |
---|---|
DISPLAY | 运行图形界面环境时的名称 |
EDITOR | 用于文本编辑的程序名称 |
SHELL | 本机 shell 名称 |
HOME | 本机主目录的路径名 |
LANG | 定义了本机语言的字符集和排序规则 |
OLD_PWD | 先前的工作目录 |
PAGER | 用于分页输出的程序名称。通常设置为 /user/bin/less |
PATH | 以冒号分割的一个目录列表,当用户输入一个可执行程序的名称时,会查找该目录列表 |
PS1 | 提示符字符串1. 定义了本机 shell 系统提示符的内容 |
PWD | 当前工作目录 |
TERM | 终端类型的名称。此变量设定了本机终端模拟器使用的协议 |
TZ | 用于指定本机所处的时区 |
USER | 用户名 |
环境是如何建立的
用户登录系统后,bash 程序会启动并读取一系列称为启动文件的配置脚本,这些脚本定义了所有用户共享的默认环境。接下来,bash 会读取更多存储在主目录下的用于定义个人环境的启动文件。
login 和 non-login shell
shell 会话存在两种类型,分别为 login shell
会话和 non-login shell
会话
login shell
会话会提示用户输入用户名和密码,如虚拟控制台会话,而我们在 GUI 中启动的终端会话就是一个典型的 non-login shell
会话
login shell
的启动文件
文件 | 说明 |
---|---|
/etc/profile | 适用于所有用户的全局配置脚本 |
~/.bash_profile | 用户的个人启动文件。可扩展或重写全局配置脚本的配置 |
~/.bash_login | 若 ~/.bash_profile 缺失,则 bash 尝试读取此脚本 |
~/.profile | 若上面两个文件缺失,则读取此文件 |
non-login shell
的启动文件
文件 | 内容 |
---|---|
/etc/bash.bashrc | 适用于所有用户的全局配置脚本 |
~/.bashrc | 用户的个人启动文件 |
此外 non-login shell
还会继承父类进程的环境,父类进程通常是一个 login shell
用户可查看本机系统有哪些启动文件,它们通常是以 .
开头,所以用户在使用 ls
命令时,需要伴随使用 -a
选项。
启动文件中有什么
当用户输入命令 ls
,shell 不会搜索整个系统来寻早 /bin/ls
,而是会搜索 PATH
变量中存储的目录列表。
PATH
变量通常是由启动文件 /etc/profile
中的一段代码设定
PATH=$PATH:$HOME/bin
这段代码将 $HOME/bin
添加到了 PATH
值的尾部。当系统需要检索用户输入的命令时, $HOME/bin
这个路径就会处于被搜索的路径列表中。
修改环境
现在用户已经知道了系统启动文件的位置和内容,就可以修改启动文件来定义我们的环境
用户应该修改哪些环境
一般来说,在 PATH 中添加目录,或定义额外的环境变量,需要将这些更改放入到 .bash_profile
文件中,当然用户也可以修改其他目录下的文件,比如 /etc
下的 profile 文件。
文本编辑器
文本编辑器类似于字处理器,它允许用户通过移动移动光标到方式来编辑屏幕中的文字,与字处理器不同,文本编辑器只支持纯文本,它是软件开发人员编写代码的主要工具,系统管理员也可以使用文本编辑器来管理系统的配置文件
文本编辑器分为两种,图形界面和基于文本的。GNOME 和 KDE 都配备有一些流行的图形界面编辑器,GNOME 配备的编辑器叫 gedit,KDE 则配备了三种编辑器,分别是 kedit、kwrite 和 kate(复杂程度递增)
基于文本的编辑器中有 nano、vim 和 emacs
使用文本编辑器
使用 gedit 直接 gedit some_file
,如果没有输入的文件名会新建
当更改系统文件时,需要为文件备份,可以给复制的文件加上扩展名 .bak
, .sav
, .old
, .orig
等
当更改 .bashrc
文件后,需要使用 source .bashrc
来让 bash 重新读取 .bashrc 文件
VI 简介
为什么要学习 vi
现在这个时代存在着很多图形界面编辑器和易用的基于文本的编辑器,例如 nano,那么为什么要学习 vi?有三条充分的理由
- vi 总是可用的。如果用户面前的系统没有图形界面,例如是远程服务器或是本地系统的 X 配置不可用,那么 vi 就会成为救命的稻草。
- vi 是轻量级的软件,运行速度快,对很多任务来说,启动 vi 更便捷
- 用户不想被其他 Linux 和 UNIX 用户蔑视
VI 背景
大多数 LInux 发行版配备的不是真正的 vi 而是 vi 加强版——vim(Vi Improved 的缩写)
VI 操作
启动和退出
vi
启动 vi
:q
退出 vi,如果应为一些原因,vi 不能够退出,可以通过在命令后添加感叹号的方式强制退出 vi, :q!
进入插入模式
vi 是一个模态编辑器,vi 启动后进入的是命令模式,在命令模式中,几乎键盘上每一个按键都代表一条命令
可以按 i
进入插入模式,此时用户可以进行输入操作
保存工作
要保存用户修改后的文件,需要在命令模式下输入一条 ex 命令,也就是按 :
键,之后输入 w
:w
,文件写入硬盘驱动器后,用户会在屏幕底部得到一条确认信息
移动光标
在命令模式下,vi 提供了很多移动光标命令,其中一些命令是与 less
命令共用的
L
或右方向键:右移一行
H
或左方向键:左移一行
J
或下方向键:下移一行
K
或上方向键:上移一行
数字 0:至本行开头
shift + 6
:至本行第一个非空字符
shift + 4
:至本行末尾
W
:至下一单词或标点的开头
shift + w
:至下一单词的开头,忽略标点
B
:至上移单词的开头
shift + b
:至上移单词的开头,忽略标点
ctrl + f
或 page Down
:下翻一页
ctrl + b
或 page Up
:上翻一页
number + shift + G
:至第 number 行
shift + G
至文件最后一行
很多 vi 的命令的前面都可以缀上数字。前缀数字可以控制命令执行的次数,比如 5j
可以使得光标下移 5 行
基本编辑
插入、删除、剪切、赋值等构成了基本的文本编辑操作,同时 vi 还支持有限形式的撤销错做,在命令模式下按 U
键就可以撤销用户最后一步操作
添加文本
shift + a
:光标移动至行尾并进入插入模式
插入一行
插入文本的另一种方式是在文本中重开一行,即在两行现存的文字中间插入空白行并进入插入模式
o
:当前行的上方
shift + o
:当前行的下方
删除文本
就像用户期望的一样,vi 提供了很多种删除文本的方式,每一种都需要进行一次至两次的按键操作。首先, x
键会删除光标处的字符,它也可以加数字前缀来明确删除的字数。 D
键则使用得更加普遍,它也可以加数字前缀来明确删除的字数
x
:当前字符
3x
:当前字符和之后的 2 个字符
dd
:当前行
5dd
:当前行和之后 4 行
dW
:当前字符到下一单词的起始
d$
:当前字符到当前行的末尾
d0
:当前字符到当前行的起始
d^
:当前字符到当前行的下一个非空字符
dG
:当前行到文件末尾
d20G
:当前行到文件第 20 行
剪切、复制和粘贴文本
命令 d
不是在删除文本而是在剪切文本。用户每次使用 d
命令之后,都会复制删除的内容进缓存,然后用户就可以使用 p
命令将缓存中的内容粘贴到光标之后或使用 p
命令将内容粘贴到光标之前
与命令 d
剪切文本的形式一样,命令 y
会复制文本
yy
当前行
5yy
当前行和之后 4 行
yW
:当前字符到下一单词的其实
y$
:当前字符到当前行的末尾
y0
:当前字符到当前行的起始
y^
:当前字符到当前行的下一个非空字符
yG
:当前字符到文件末尾
y20G
:当前字符到文件第 20 行
合并行
vi 在行的概念上非常严格,通常将光标移动到行的末端并删除行的末尾字符并不能将此行与下一行合并。因此,vi 专门提供了 J
命令
查找与替换
vi 提供了在一行或整个文件中,根据搜索条件将光标移动到指定位置的功能。vi 还可以执行文本替换工作,用户可指定替换时是否需要用户确认
行内搜索
命令 f
在行内进行搜索,并将光标移至搜索到的下一个指定字符,比如,命令 fa
就会将光标移动到本行下一处出现字符 a
的地方,在执行过一次行内搜索之后输入分号可以使 vi 重复上一次的搜索
搜索整个文件
命令 /
可以完成对单词或短语的搜索,当用户使用 /
命令后,一个 /
符号就会出现在屏幕的底部,接下来,输入需要搜索的代持或短语,以 Enter
结束。光标就会移动到下一出包含被搜索字符串的地方,使用 n
命令可以重复此搜索,vi 同样也支持正则表达式
全局搜索和替换
vi 使用 ex 命令来执行几行之内或整个文件中的搜索和替换操作,输入以下命令可将文件中的 Line
替换为 line
:%s/Line/line/g
现在就来解析这条命令每一部分的功能
:
:分号用于启动一条 ex 命令
%
:确定了操作作用的范围, %
表示从文件第一行到最后一行,本命令还可表示为 1, $
,或 1, 5
(本文件只有 5 行),如果不明确指出命令的作用范围,则命令只在本行生效
s
:指定了具体操作——本次是替换操作
/Line/line
搜索和替换的文本
g
:代指全局,也就是说对搜索到底每一行的每一个实例进行替换,如果 g
缺失,那么只替换每一行第一个符合条件的实例
在命令末尾添加 c
则命令在每次替换之前都会请求用户确认
:%s/Line/line/gc
此命令会将文件替换为原来的样子,但是每次替换前,vi 都会停下来询问用户是否确认执行替换
replace with Line (y/n/a/q/l/^E/^Y)?
圆括号中每一字符都是一个可能的回答,下表阐述了每一个字符的含义
y
:执行替换
n
:跳过此次替换
a
:执行此次替换和之后的所有替换
q或ESC
:停止替换
l
:执行此次替换并停止替换,是 last
的缩写
Ctrl + E
或 Ctrl + Y
分别是向下滚动和向上滚动,能用于查看替换出的上下文
编辑多个文件
用户经常遇到需要同时编辑多个文件的情况。可能是需要对多个文件做出修改,或是拷贝文件的部分内容到另一个文件。用户可以通过在命令行具体指定多个文件的方式使 vi 打开多个文件
vi file1 file2 file3...
切换文件
使用以下 ex 命令来从一个文件切换到下一个文件
:n
切换回上一个文件
:N
当用户从一个文件切换到另一个的时候,vi 要求用户必须先保存对当前文件做出的修改才能切换到其他文件。若要放弃对文件的修改并使 vi 强制切换到另一个文件,可在命令后添加感叹号 !
除了以上描述的切换方法之外,vim 还提供了一些 ex 命令让用户可以更轻松地编辑多个文本。用户可以使用 :buffers
来查看正在编辑的文件列表
输入 :buffer
加文件编号可切换到另一个文件
载入更多的文件
我们以可以在现有的编辑会话中载入更多的文件,使用 ex 命令 :e
加文件名可以载入另一个文件。先退出现有的编辑会话并回到命令行模式
:e file
文件之间的内容复制
用户在编辑多个文件的过程中,有时会需要将一个文件中的一部分复制到另一个文件中。使用之前使用过的复制和粘贴命令即可完成此功能
使用 :buffer 1
切换到文件 1,之后使用 yy
命令复制第一行,使用 :buffer 2
来切换到文件 2 进行粘贴
插入整个文件
用户可以将一个文件完全插入正在编辑的文件中。
通过 vi file1
打开文件,使用 :r foo.txt
可以将指定文件内容插入到光标位置之前
保存工作
vi 提供了很多方式保存编辑过的文件,前面已经介绍过 :w
,但是还是有其他可用的方法,当命令 :w
指定一个随意的文件名时,命令的功能就类似于另存为,例如用户在编辑 foo.txt
的时候想要将其另存为 foo1.txt
,那么就可以输入如下内容
:w foo1.txt