Linux基础(2)

正则表达式(也称为“regex”或“regexp”)是一种用来描述文本模式的特殊语法。在 Linux 系统上,正则
表达式通常被用来查找文本的模式,以及对文本流执行“搜索-替换”操作以及其它功能。
当我们看到正则表达式时,您可能发现正则表达式的语法看起来与我们上一篇教程,但是,不要让它欺骗您;
它们的类似性只是表面的。虽然正则表达式和文件名匹配替换模式可能看上去相类似,但是它们是根本不同的
两种类型。
记住那个警告,让我们看一下最基本的正则表达式,简单子串。为了这样做,我们要使用 grep,它是一个扫描
文件内容来查找适合特定正则表达式的命令。grep 打印与正则表达式匹配的每一行,并忽略与之不匹配的每一
行:
$ grep bash /etc/passwd
operator:x:11:0:operator:/root:/bin/bash
root:x:0:0::/root:/bin/bash
ftp:x:40:1::/home/ftp:/bin/bash
在上面的命令中,grep 的第一个参数是一个正则表达式;第二个参数是一个文件名。grep 读取 /etc/passwd 中
的每一行并对它应用简单子串正则表达式 bash 来查找匹配项。如果找到一个匹配项,那么 grep 打印出整行;
否则,忽略该行。
使用正则表达式,可以利用元字符来执行比我们至今已研究过的示例复杂得多的搜索。这些元字符中的一个是
.(点),它与任何单个字符匹配:
$ grep dev.hda /etc/fstab
/dev/hda3    /           reiserfs      noatime,ro 1 1
/dev/hda1    /boot         reiserfs     noauto,noatime,notail 1 2
/dev/hda2    swap           swap         sw 0 0
#/dev/hda4     /mnt/extra     reiserfs     noatime,rw 1 1
在本示例中,文字文本 dev.hda 没有出现在 /etc/fstab 中的任何一行中。但是,grep 扫描这些行时没有查找文
字 dev.hda 字符串,而是查找 dev.hda 模式。请记住 . 将与任何单个字符相匹配。正如您看到的,. 元字符在
功能上等价于 glob 扩展中 ? 元字符的工作原理。
如果我们希望与比 . 更具体一点地来匹配字符,那么我们可以使用 [ 和 ](方括号)来指定要匹配的字符子集:
$ grep dev.hda[12] /etc/fstab
/dev/hda1     /boot        reiserfs noauto,noatime,notail 1 2
/dev/hda2     swap          swap     sw 0 0
正如您看到的,这个特殊语法的作用与“glob”文件名扩展中的 [] 相同。同样,这是学习正则表达式的难点之
一 — 这个语法与“glob ”文件名扩展语法类似,但又不尽相同,它经常给学习正则表达式的人带来困惑。
通过使 [ 后面紧跟一个 ^,您可以使方括号中的意思相反。在本例中,方括号将与未列在方括号内的任意字符
匹配。同样,请注意我们在正则表达式中使用 [^] ,而在 glob 中使用 [!] :
$ grep dev.hda[^12] /etc/fstab
/dev/hda3      /          reiserfs      noatime,ro 1 1
#/dev/hda4      /mnt/extra     reiserfs     noatime,rw 1 1
注意下面一点很重要:方括号内部的语法根本不同于正则表达式其它部分中的语法。例如,如果在方括号内放
置一个 . ,那么它允许方括号与文字 . 匹配,就象上面示例中的 1 和 2。比较起来,除非有 / 作为前缀,否则
方括号外面的文字 . 被解释为一个元字符。通过输入如下命令,我们可以利用这一事实来打印 /etc/fstab 中包
含文字串 dev.hda 的所有行的列表:
$ grep dev[.]hda /etc/fstab
或者,我们也可以输入:
$ grep "dev/.hda" /etc/fstab
这两个正则表达式都不可能与您的 /etc/fstab 文件中的任何行相匹配。
某些元字符本身不匹配任何字符,但却修改前一个字符的含义。一个这样的元字符是 * (星号),它用来与前
一个字符的零次或者多次重复出现相匹配。这里是一些示例:
ab*c(与 abbbbc 匹配但不与 abqc 匹配)
ab*c(与 abc 匹配但不与 abbqbbc 匹配)
ab*c(与 ac 匹配但不与 cba 匹配)
b[cq]*e(与 bqe 匹配但不与 eb 匹配)
b[cq]*e(与 bccqqe 匹配但不与 bccc 匹配)
b[cq]*e(与 bqqcce 匹配但不与 cqe 匹配)
b[cq]*e(与 bbbeee 匹配)
.*(与任何字符串匹配)
foo.*(与以 foo 开始的任何字符串相匹配)
ac 行与正则表达式 ab*c 相匹配,因为星号也允许前面的表达式(b)出现零次。请注意解释 * 正则表达式元字
符所用的方法与解释 * glob 字符的方法根本不同。
我们在这里要详细描述的最后几个元字符是 ^ 和 $ 元字符,它们用来分别与行的开始和结束相匹配。通过在正
则表达式开始处使用一个 ^ ,您可以将您的模式“锚定”在行的开始。在下面的示例中,我们使用 ^# 正则表
达式来与以 # 字符开始的任何行相匹配:
$ grep ^# /etc/fstab
# /etc/fstab: static file system information.
#
Filesystem Hierarchy Standard 是指定 Linux 系统上目录布局的文档。FHS 被设计来提供一个通用布局以简化
与分布无关的软件开发。FHS 指定下列目录(直接来自 FHS 规范):
/(根目录)
/boot(引导装入程序的静态文件)
/dev(设备文件)
/etc(主机特定的系统配置)
/lib(基本共享库和核心模块)
/mnt(临时挂装文件系统的挂装点)
/opt(附加的应用程序软件包)
/sbin(基本系统二进制文件)
/tmp(临时文件)
/usr(辅助层次结构)
/var(可变数据)
FHS 的布局规范基于存在两个独立的文件类别:可共享与不可共享以及可变与静态这一思想。可共享数据能在
主机之间被共享;不可共享数据特定于给定主机(例如配置文件)。可变数据可以被修改;静态数据不可以被
修改(除了在系统安装和维护阶段)。
下面的表格概述了四种可能的组合,并列出了与那些类别相符的目录示例。这个表还是直接取自 FHS 规范:
  +---------+-----------------+-------------+
          | 可共享          | 不可共享 |
  |
  +---------+-----------------+-------------+
  |静态 | /usr              | /etc        |
  |       | /opt         | /boot        |
  +---------+-----------------+-------------+
  |可变 | /var/mail            | /var/run |
  |       | /var/spool/news | /var/lock |
  +---------+-----------------+-------------+
在 /usr 下,您会发现一个看上去与根文件系统非常相似的辅助层次结构。当机器打开并运行时,/usr 的存在并
不重要,所以能在网络上共享它(“可共享”),或者从 CD-ROM 上挂装它(“静态”)。大多数 Linux 设
置不利用 /usr 的共享,但是理解根目录中主层次结构和 /usr 中辅助层次结构之间的区别的用处是有价值的。
这就是我们要说的有关 Filesystem Hierarchy Standard 的所有内容。该文档本身非常具有可读性,所以您应该
去看一下。我们承诺如果您读了它,那么您将对 Linux 文件系统理解得更多。
Linux 系统通常包含数十万个文件。可能您非常精明能干,从未丢失它们中的任何一个,但是更可能的是,您
偶尔在查找一个文件时需要帮助。Linux 上有几个不同的工具用于查找文件。下面的演示将向您介绍它们,并
帮助您选择适合您的工作的工具。
当您在命令行上运行程序时,bash 实际上搜索目录列表来查找您所请求的程序。例如,当您输入 ls,bash 实
质上不知道 ls 程序位于 /usr/bin。但是,bash 引用一个名为 PATH 的环境变量,它是一个用冒号分隔的目录
列表。我们可以检查 PATH 的值:
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin
给定了 PATH 的值(您的可以不同),bash 将首先检查 /usr/local/bin,然后是 /use/bin 以搜索 ls 程序。ls 最
有可能被保存在 /usr/bin 内,所以 bash 在那里停止。
您可以通过在命令行上为 PATH 指派元素来扩充它:
$ PATH=$PATH:~/bin
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/home/agriffis/bin
您也可以除去 PATH 上的元素,尽管这不是那么容易,因为您不能引用现有的 $PATH。最好的办法是简单输
入您想要的新 PATH:
$ PATH=/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:~/bin
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/home/agriffis/bin
最后,您应该知道 -a 标志,它使 which 向您显示您的 PATH 中给定程序的所有实例:
$ which -a ls
/usr/bin/ls
/bin/ls
最后,您应该知道 -a 标志,它使 which 向您显示您的 PATH 中给定程序的所有实例:
$ which -a ls
/usr/bin/ls
/bin/ls
如果您不只对程序位置感兴趣,而且想要找到更多信息,那么可以尝试 whereis 程序:
$ whereis ls
ls: /bin/ls /usr/bin/ls /usr/share/man/man1/ls.1.gz
这里我们看到 ls 出现在两个常见二进制位置 /bin 和 /usr/bin 中。另外,我们被告知手册页定位在
/usr/share/man 。如果您要输入 man ls,那么这就是您将看到的手册页。
whereis 程序还具有搜索源代码、指定备用搜索路径和搜索不寻常项的能力。
find 命令是您工具箱中的另一个工具。使用 find,您不会受限于程序;通过使用多种搜索标准,您能搜索您想
要的任何文件。例如,要搜索 /usr/share/doc 目录下名为 README 的文件:
$ find /usr/share/doc -name README
/usr/share/doc/ion-20010523/README
/usr/share/doc/bind-9.1.3-r6/dhcp-dynamic-dns-examples/README
/usr/share/doc/sane-1.0.5/README
您可以在 -name 的参数中使用“glob”通配符,前提条件是您用双引号引用了它们或用反斜杠进行了转义(这
样它们就能被完整地传递到 find 而不是被 bash 扩展)。例如,我们可能想要搜索带有扩展名的 README 文
件:
$ find /usr/share/doc -name README/*
/usr/share/doc/iproute2-2.4.7/README.gz
/usr/share/doc/iproute2-2.4.7/README.iproute2+tc.gz
/usr/share/doc/iproute2-2.4.7/README.decnet.gz
/usr/share/doc/iproute2-2.4.7/examples/diffserv/README.gz
/usr/share/doc/pilot-link-0.9.6-r2/README.gz
/usr/share/doc/gnome-pilot-conduits-0.8/README.gz
/usr/share/doc/gimp-1.2.2/README.i18n.gz
/usr/share/doc/gimp-1.2.2/README.win32.gz
/usr/share/doc/gimp-1.2.2/README.gz
/usr/share/doc/gimp-1.2.2/README.perl.gz
[578 additional lines snipped]
当然,您可能想要在搜索中忽略大小写:
$ find /usr/share/doc -name '[Rr][Ee][Aa][Dd][Mm][Ee]*'
或者,更简单:
$ find /usr/share/doc -iname readme/*
正如您看到的,您能使用 -iname 来进行不区分大小写的搜索。
如果您熟悉正则表达式,那么使用 -regex 选项将把输出限制成匹配某一模式的文件名。与 -iname 选项类似,
它有一个相应的 -iregex 选项,该选项忽略模式中的大小写。例如:
$ find /etc -iregex '.*xt.*'
/etc/X11/xkb/types/extra
/etc/X11/xkb/semantics/xtest
/etc/X11/xkb/compat/xtest
/etc/X11/app-defaults/XTerm
/etc/X11/app-defaults/XTerm-color
请注意:不象许多程序,find 要求指定的正则表达式与整个路径匹配,而不只是该路径的一部分。为此,指定
前导和尾随的 .* 是必要的;只使用 xt 是不够的。
-type 选项允许您查找某一类型的文件系统对象。可能的 -type 参数是 b (块设备)、c(字符设备)、d(目
录)、p(命名管道)、f(常规文件)、l(符号链接)和 s(套接字)。例如,要在 /uer/bin 中搜索包含字符
串 vim 的符号链接:
$ find /usr/bin -name '*vim*' -type l
/usr/bin/rvim
/usr/bin/vimdiff
/usr/bin/gvimdiff
如果您另外指定了 -daystart 选项,那么时间周期以今天的开始时为开始,而不是 24 小时之前。例如,这是昨
天和前天创建的一组文件:
$ find . -name /? -daystart -mtime +0 -mtime -3
./b
./c
$ ls -l b c
-rw------- 1 root root           0 Jan 6 18:00 b
-rw------- 1 root root           0 Jan 5 18:00 c
-size 选项允许您根据文件的大小来查找它们。缺省情况下,-size 的参数是 512 个字节的块,但是添加后缀可
以使操作更简便。可用的后缀是 b(512 字节的块)、c(字节)、k(千字节)和 w(2 字节的字)。另外,
您可以在前放置加号(“大于”)或者减号(“小于”)。
例如,要在 /usr/bin 中查找小于 50 个字节的常规文件:
$ find /usr/bin -type f -size -50c
/usr/bin/krdb
/usr/bin/run-nautilus
/usr/bin/sgmlwhich
/usr/bin/muttbug
您可能在想如何处理所有这些找到的文件!不用担心,通过使用 -exec 选项,find 具有对它找到的文件进行操
作的能力。这个选项接受命令行作为它的参数来执行,它以 ; 中断,并用文件名来替换任何出现的 {} 。下面这
个示例可以帮助您完全理解它:
$ find /usr/bin -type f -size -50c -exec ls -l '{}' ';'
-rwxr-xr-x 1 root root             27 Oct 28 07:13 /usr/bin/krdb
-rwxr-xr-x 1 root root             35 Nov 28 18:26 /usr/bin/run-nautilus
-rwxr-xr-x 1 root root             25 Oct 21 17:51 /usr/bin/sgmlwhich
-rwxr-xr-x 1 root root             26 Sep 26 08:00 /usr/bin/muttbug
正如您看到的,find 是一个功能非常强大的命令。在 UNIX 和 Linux 开发的几年中,它获得了发展。find 中还
有许多其它有用的选项。您可以在 find 手册页中学习它们。
我们已经学习了 which、whereis 和 find。您可能已经注意到执行 find 要花一些时间,因为它需要读取它正在
搜索的每个目录。事实表明 locate 命令可以通过依靠外部数据库来加速操作。
locate 命令与路径名的任何部分相匹配,而不只是文件本身。例如:
$ locate bin/ls
/var/ftp/bin/ls
/bin/ls
/sbin/lsmod
/sbin/lspci
/usr/bin/lsattr
/usr/bin/lspgpot
/usr/sbin/lsof
大多数 Linux 系统包含一个周期性的进程来更新这个数据库。如果您的系统在运行上述命令时返回如下错误,
那么您需要运行 updatedb 来生成搜索数据库:
$ locate bin/ls
locate: /var/spool/locate/locatedb: No such file or directory
$ su
Password:
# updatedb
运行 updatedb 命令可能要花很长时间。如果您硬盘的噪音很大,那么将听到许多吵闹声,因为这正在为整个
文件系统建立索引。
为了恢复提示符,您可以输入 Control-C(通常写为 Ctrl-C 或 ^C):
^C
$
您获得了一个新的 bash 提示符,但 xeyes 窗口消失了。事实上,整个进程已被杀死。如果不通过 Control-C
来杀死它,我们还可以使用 Control-Z 来使它只是停止:
$ xeyes -center red
^Z
[1]+ Stopped          xeyes -center red
$
这次您获得了一个新的 bash 提示符,并且 xeyes 窗口依然保留着。但是,如果您试图稍微移动这个窗口,那
么将注意到眼球在某一位置被冻结了。如果 xeyes 窗口被另一个窗口遮盖,然后又出现,那么您将看到它根本
不会重绘眼睛。进程没有做任何操作。事实上,它是“被停止了”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值