2005年11月01日

好久没有碰FreeBSD了。。。现在终于有空了,也有心思了,好好搞搞。。

2004年08月18日
在这里简单介绍一下安装方法。首先下载http://ftp.vxin.com/download/OpenQ-ports-0.30-4.tar.bz2文件以下是解压后此目录中的README:如过以前安装过OpenQ ports请现卸载掉OpenQ# cd /usr/ports/chinese/OpenQ/# make deinstall# rm -rf /usr/ports/chinese/OpenQ

没安装过的可以直接从这里开始。

# tar jxvf OpenQ-ports-0.30-4.tar.bz2# cd OpenQ-ports-0.30-4/ports/chinese/# mv OpenQ /usr/ports/chinese/# cd /usr/ports/chinese/OpenQ/# make install clean在这里提示下.安装它所依赖的包nss的时候可能会出错,建议单独到/usr/ports/security/nss/下手动先安装:make install clean,如果是一来就直接在OpenQ目录里make install clean出错了的话,请到nss目录下删除work后再装,装完再回到OpenQ目录删除work,再执行:make install clean,装完后执行gaim就能用了。

NetBSD 与 OpenBSD 更相似一些(其实应该反过来说才更确切)。就操作系统而言,我现在能想到的有这些区别(用即将推出的 2.0 版做比较):

- 没有 /stand/sysinstall,配置一般用命令行。有一个叫 sushi 的 program 是个菜单式的系统管理界面,但有些东西好像还不 work。
- 网卡的配置文件是 /etc/ifconfig.<if#>,<if#> 可以是 fxp0, xl0 等,每个网卡一个文件。
- Daemon 的启动用的是 NetBSD 的 rc.d 系统,该系统已经被 FreeBSD 5.x 采纳,所以如果用过 5.x 的话应该不陌生。
- 默认的 shell 是 csh (FreeBSD 用得实际上是 tcsh)。
- FreeBSD 用了 PAM,NetBSD 没有用,但 PAM 在 pkgsrc 里有。
- NetBSD 采用的 nsswitch,FreeBSD 好像没有。
- NetBSD 采用 raidframe,FreeBSD 采用 vinum。但这两者都已移植到了对方的系统。
- NetBSD 的防火墙采用 ipfilter,-current 里还加入了 OpenBSD 的 pf。在 NetBSD 2.0 里,可以采用 pkgsrc-wip 里的 pflkm 来加入 pf 的支持。FreeBSD 的防火墙诸位都应该比较熟悉了,我就不多说了。

另外一个显著的不同是 NetBSD 的 pkgsrc。尽管它是从 FreeBSD 的 ports 派生的,但在其后的演化中加入了许多新特性,比如用 buildlink 替代 DEPENDS,等等。与 FreeBSD 的 ports 比较,有这些不同:

- 软件安装的 prefix 是 /usr/pkg,而不是 /usr/local(当然如果你愿意,还可以把它变为 /usr/local)。这样做的好处就是,从源码编译安装的软件仍然可以安装到 /usr/local,而不与 NetBSD 的 pkg 混在一起。当然 FreeBSD 也可以把 prefix 设为不是 /usr/local,但不是所有的 package 都遵循,有的 package 使用 hardcode 的 prefix (/usr/local)。

- pkgsrc 把一个 software package 的不同的模块分解到不同的 pkg 里,这也是我比较喜欢 pkgsrc 的比较重要的一点。比如说,对于 php4 这个 pkg,在 FreeBSD 下就需要在编译时选择编译哪些模块,如果安装以后想要再增加新的模块(或去掉不用的模块),就需要重新编译。NetBSD 则不然,比如说你想安装 php4-mysql,在安装 php4 后,再进入 /usr/pkgsrc/databases/php4-mysql,然后 make && make install 就可以了,其他的 php4 模块也是如此。其他的例子还有 subversion,在 FreeBSD 下你或者安装 subversion,或者安装 subversion-python。在 pkgsrc 下,你可以安装 subversion-base,然后安装 py-subversion,还可以安装 ap2-subversion (apache2 的 webdav support),等等。在这一点上,我觉得 pkgsrc 有点象 Debian,把一个软件包拆成不同的功能块,分别放在不同的 pkg 里面。

- pkgsrc 不仅可以在 NetBSD 上使用,也可以在各种不同的 Linux distribution, FreeBSD, OpenBSD, Solaris, IRIX, AIX, Darwin (Mac OS X)。我个人就在 Linux 和 Solaris 上用过。

- pkgsrc 里的 pkg 虽然不如 FreeBSD 里面的多(因为要兼顾 NetBSD 支持的各种平台),但许多 missing 的 pkg 可以在 pkgsrc-wip (http://pkgsrc-wip.sourceforge.net/) 里面找到。wip 是 work in progress 的意思,一个 pkg 在加入 pkgsrc 之前,要经过 wip。wip 里面的 pkg 大多数都能很好地支持 i386,所以在 i386 上可以作为 pkgsrc 的补充。比如 jdk14 (这个是 NetBSD native 的),pflkm 现在还都是在 wip 里面。

2004年08月15日

一下对gnome2.6.2有用…
#cd /usr/ports/x11-fonts/ttmkfdir  
#make install clean
2)#mkdir -p /usr/X11R6/lib/X11/fonts/TT
进入你的WIN分区找到simsun.ttc和tahoma.ttf
# mount_msdosfs /dev/ad0s1 /mnt
# cd /mnt/WINDOWS.0/Fonts/   (这里是我的机器目录)
#cp simsun.ttc /usr/X11R6/lib/X11/fonts/TT/simsun.ttf
#cp tahoma.ttf /usr/X11R6/lib/X11/fonts/TT
#cd /usr/X11R6/lib/X11/fonts/TT
#ttmkfdir >fonts.dir
#cp fonts.dir fonts.scale
做完上面的步骤后就修改下几个配置文件:
1)# cd /etc/X11/  (有些系统是/usr/X11R6/etc/)
# emacs XF86Config-4 (大开X的配置文件)
找到Section “Module” 节,大概如下:
Section “Module”
        Load  “extmod”
        Load  “glx”
        Load  “dri”
        Load  “dbe”
        Load  “record”
        Load  “xtrap”
        Load  “speedo”
        Load  “type1″
        Load  “xtt”   —>需要我们添加的
EndSection
添加完后保存退出.
然后现在修改
/usr/X11R6/etc/fonts/fonts.conf 文件
打开此文件,加入如下内容
 
     
         12
     

     
         false
     


然后保存退出!
现在安装fcitx输入法
首先在~/.profile里加入:
LANG=zh_CN.eucCN
LC_ALL=zh_CN.eucCN
export LANG LC_ALL
然后在~/.xinitrc文件中加入:
export XMODIFIERS=@im=fcitx
fcitx&
好,现在退出shell和X重新登陆一次,再输入startx进入你的桌面,哈哈,全部是中文了吧!
主意用ctrl+sparc唤醒输入法,好了汉化就大概如此了,自己感觉效果还不错,浏览网站跟IE差不多.


2004年08月11日

1、开机时进入:
……
Booting [kernel] in 10 seconds…

当出现上面提示后,输入 unload(本输入看不见,就像输入密码一样,别的输入也应该可以) ,回车
然后输入: boot -s ,回车即可进入单用户模式

2、从多用户模式进入
#shutdown now

3、从多用户模式进入
#kill -TERM 1

2004年08月09日

周末在家里用ports tree装gnome2,唉..太..慢了,花了至少有11-12个小时,到今天早晨起来为止才看见正在下Mozilla,晕死..由于要上班了,只好Ctrl+c,等晚上回来继续make install clean..

2004年08月07日

 過去的困惑 – 傳統方法的缺點
僅管FreeBSD提供ports及packages來管理應用程式,但還是有很多問題。最常
見的問題在於應用程式的重覆安裝、相依性及升級。
以我的個人電腦為例,雖然裝的應用程式不多,確發生了上述的問題。
我先安裝lynx,以提供文字模式下的網頁瀏覽工具。
# cd /usr/ports
# make update
# make index
# cd /usr/ports/www/lynx
# make install clean
後來安裝X window system,並且使用mozilla瀏覽器,提供X的網頁瀏覽工具。
# cd /usr/ports/www/mozilla
# make install clean
但安裝完成後,我發現兩套應用程式都需要gettext,
# pkg_info | grep gettext
gettext-0.11.1_1 GNU gettext package
gettext-0.11.1_3 GNU gettext package
雖然lynx以及mozilla皆可以正常?#092;作,但總覺得安裝兩套gettext有點浪費硬碟
空間,於是決定把其中一個移除。
先移除舊版的 gettext
# pkg_delete gettext-0.11.1_1
pkg_delete: package ‘gettext-0.11.1_1′ is required by these other packages
and may not be deinstalled:
lynx-2.8.5d7_1
發現和 lynx 有相依性存在,若要移除舊版的 gettext,必須先移除 lynx。
文字方塊: v 1.2
移除新版的試試看
# pkg_delete gettext-0.11.1_3
pkg_delete: package ‘gettext-0.11.1_3′ is required by these other packages
and may not be deinstalled:
ORBit-0.5.15_1
gmake-3.79.1_1
gtk-1.2.10_4
mozilla-1.0.rc3,1
windowmaker-0.80.0_1
zh-xcin-2.5.3.p2_1
zh-xmms-1.2.7_1
vim-6.1.48
mod_php4-4.2.1_1
AbiWord-1.0.1
zh-zhcon-0.2_4
真是糟糕,無論舊版或是新版都有相依性存在。看來目前只好先暫時打消念頭。
三天後,我檢查是否有可以升級的應用程式。
先更新ports tree
# cd /usr/ports
# make update
# make index
root@polo [/usr/ports] # pkg_version -L =
gettext <
png <
顯示目前系統 gettext 及 png 的版本比 ports tree還舊。由於系統中有安裝二個
不同版本的 gettext,表示其中一套是需要升級的,而另一套符合目前最新的版
本。
首先我們先升級gettext。通常我們都會先移除舊版的應用程式,再安裝新版的應
用程式;因為新版的我們已經安裝了,所以只須移除舊版的即可。此時,問題就
發生了,和前述一樣,會發生相依性的關係,只好作罷。

接下來我們試著升級png。
# pkg_delete png-1.2.2_4/
pkg_delete: package ‘png-1.2.2_4′ is required by these other packages
and may not be deinstalled:
mozilla-1.0.rc3,1
windowmaker-0.80.0_1
gd-2.0.1_3
mod_php4-4.2.1_1
AbiWord-1.0.1
和gettext一樣,發生相依性的關係。後來我決定改試強制性升級,雖然這種方
法危險性很大。
root@polo [/var/db/pkg] # pkg_delete -f png-1.2.2_4/
再安裝新版的png
root@polo [/usr/ports/graphics/png] # make install clean
但後來我發現原本和舊版png有相依性的應用程式,沒有因為我升級而將相依關
係取代為新版的png。
以上這些常見的問題,真是令人頭痛。
● 新世紀的交替 – 智慧型管理的時代
○ pkgtools的相關程式
lang/ruby – An object-oriented interpreted scripting language
devel/ruby-fnmatch – A Ruby module which provides File::fnmatch and File::FNM_*
devel/ruby-bdb1 – Ruby interface to Berkeley DB revision 1.8x with full feature support
devel/ruby-optparse – Yet another command line option parser for Ruby
sysutils/pkg_tarup – Generates binary package from installed package
(data from: pkgtools announce news)

安裝之前,確定ports tree是最新的,雖然portupgrade目前已經趨於成熟,但不
可避免有小問題發生,還是建議安裝最新版。
# cd /usr/ports/sysutils/portupgrade
# make install clean
○ pkgtools工具簡介
portupgrade
升級已經安裝的ports或packages的工具。提供直接升級,而不須要先移除相依
性套件,甚至可以將相依性套件一起升級。
portinstall
安裝尚未安裝的套件,相當於使用`portupgrade –N`。在安裝新套件之前,會先升
級所有required套件。
portversion
將目前安裝於系統中的套件版本和ports tree的套件版本比較。這個工具是取代
原本的pkg_version,而且因為是利用ports database,所以更有效率。
ports_glob
查詢ports database的檔案。能夠判斷萬用字元,並且有能力列出特定ports的需
求、相依或主要的ports。
pkg_fetch
提供可以由遠端下載binary packages,並且會遞迴的下載相依性的packages。
pkg_glob
查詢packages database的檔案。能夠判斷萬用字元,並且有能力列出特定package
的需求、相依或主要的packages。
pkg_deinstall
這個工具是取代原本的pkg_delete。能夠判斷萬用字元,並且有能力遞迴相依性
packages,也可以選擇保留共享的函式庫。
pkg_db
pkgdb建立並升級packages的資料庫。使用了雜湊(hash)映射(map)已經安裝的
packages的名稱,這種映射方式也包含packages的來源,並將已安裝的packages

列表(list)。當安裝或移除packages的,建立好的資料庫會自動升級。
pkg_which
pkg_which會查詢packages的資料庫,並找出package是由那個檔案安裝。如果
你沒有權限升級packages的資料庫,可以找這項工作委託給 pkg_iofo(1)。
portsclean
portsclean是一個可以清理(clean)Ports的工作目錄(working directories),不再參考
distfiles,過期的packages檔案,並廢棄(obsolete)且單獨(orphan)的分享函式庫。
portcvsweb
portcvsweb可以立即經由CVSweb,瀏覽特定已知的檔案。他的功能可能比你想
像中的強大,試著隨著src、www、doc、NetBSD pkgsrc和OpenBSD ports來使
用他。
○ 開始使用 pkgtools
在使用 portupgrade 之前,先備份 /var/db/pkg。到目前為止筆者使用portupgrade
並沒有發生任何問題,但為了保留重要資料,還是強烈建議做備份動作。
# tar –zcvf backup_pkg.tgz /var/db/pkg
接下來更新ports tree 的INDEX以及建立ports的資料庫INDEX.db。
# portsdb –Uu
Updating the ports index …
…[略]
done
[Updating the portsdb <format:bdb1_btree> in /usr/ports ... - 5997 port entries
found .........1000.........2000.........3000.........4000.........5000.............. done]
然後開始進要初始設定和做一些ports的清理動作。
# pkgdb –F
[Updating the pkgdb <format:bdb1_btree> in /var/db/pkg ... - 94 packages found
(-2 +0) (...) done]
Checking the origin of AbiWord-1.0.1
Checking the origin of Hermes-1.3.2
Checking the origin of ORBit-0.5.15_1
…[略]

Duplicated origin: converters/libiconv – libiconv-1.7_3 libiconv-1.7_5
Unregister any of them? [no]
Unregister libiconv-1.7_3 keeping the installed files intact? [no]
-> libiconv-1.7_5 is kept.
–> Saving the libiconv-1.7_3’s +CONTENTS file as
/var/db/pkg/libiconv-1.7_5/+CONTENTS.libiconv-1.7_3
–> Unregistering libiconv-1.7_3
–> Done.
[Updating the pkgdb <format:bdb1_btree> in /var/db/pkg ... - 93 packages found (-1
+0) (...) done]
Stale dependency: AbiWord-1.0.1 -> png-1.2.2_4:
png-1.2.3 (score:83%) ? ([y]es/[n]o/[a]ll) [yes]
在這一步驟中,portdb發現了失效的相依性關係。原本在資料庫中的 AbiWord
是相依於 png-1.2.2_4,但後來因為之前強制移除舊版的png,並且更新png為
png-1.2.3,這些動作皆可以由portdb從packages的資料庫中偵測出來,並且還
提供建議性的相容性程度 83%。
相依性的問題是我所預期的,而且希望能夠將任何和舊版png有相依性的,全部
更正為和新版的png相依。所以我選擇 a [all]。
○ 利用pkgtools升級應用程式
更新完ports tree後,我想和packages資料庫比對一下,是否有可以升級的應用
程式。
FreeBSD的傳統方法是使用pkg_version
# pkg_version -L =
而pkgtools提供的新方法,使用資料庫比對的方式,效率更高。
# portversion –L =
libiconv <
zh-ttfm <
zip <

由結果中,可以得知在系統上有三個已安裝的應用程式版本比ports tree中的版
本還要舊。我決定先升級zh-ttfm。
和zh-ttfm相依的有
# pkg_info -rR zh-ttfm-0.9.3_1
Information for zh-ttfm-0.9.3_1:
Depends on:
imake-4.2.0_1
freetype2-2.0.9
freetype-1.3.1_2
XFree86-libraries-4.2.0_1
XFree86-clients-4.2.0_2
Required by:
zh-arphicttf-2.11_1
若想把和zh-ttfm相關的所有套件一起更新,可使用以下指令。
# portupgrade -cCrRuv zh-ttfm
若只想單純升級zh-ttfm的話,則僅使用以下指令即可。
# portupgrade -cCuv zh-ttfm
在這種例子中,應該使用後來的方式來升級,因為由之前portversion發現僅有
zz-ttfm這個應用程式需要升級,而相依性的套件並不需要升級,所以不用大費
周章升級所有相依套件。
其他範例:
.. 升級 glib
# portupgrade glib
.. 升級Xfree86和Mesa,並傳遞 -DWANT_GGI 參數來make Mesa
# portupgrade XFree86 -m ‘-DWANT_GGI’ Mesa
.. 升級sawfish以及所有sawfish依靠(depend on)的應用程式,並且建立
packages
# portupgrade -Rp sawfish
.. 升級glib,並使用互動模式(interactive)

# portupgrade -ri glib
.. 升級所有依靠(depend on) glib的應用程式,但是glib本身則不升級
# portupgrade -rfx glib glib
.. 升級所有在2002/07/08日之前安裝的應用程式
# portupgrade -f ‘<2002-07-08′
.. 升級所有依靠(depend on) png的應用程式,而且該應用程式的安裝時間在
png安裝之前
# portupgrade -fr png -x ‘>=png’
.. 只取回所有需要升級應用程式的distfiles
# portupgrade –aFR
.. 升級glib,並且以使用packages升級為優先,ports為次之
# portupgrade -P glib
.. 只使用packages,完全不考慮ports來升級所有應用程式,而且僅列出結果,
並沒有真正執行
# env PKG_PATH=/mnt/cdrom/packages/All portupgrade –anPP
.. 以相依性排序,升級所有套件。
# portupgrade -scC ‘*’
○ pkgtools.conf
如果使用ports安裝portupgrade,/usr/local/etc下可找到pkgtools.conf.sample,這
是設定pkgtools的設定樣本檔,可以依照自己的需求建立一份。
# cd /usr/loca/etc
# cp pkgtools.conf.sampl pkgtools.conf
例如:以元智server為舉例
ENV['PORTSDIR'] ||= ‘/usr/ports’
ENV['PACKAGEROOT'] = ‘ftp://freebsd.csie.nctu.edu.tw’

SANITY_CHECK = true
IGNORE_CATEGORIES = [
'french',
'german',
'hebrew',
'japanese',
'korean',
'russian',
'ukrainian',
'vietnamese',
'games',
'palm',
'print',
'x11*',
]
EXTRA_CATEGORIES = [
'outta-port',
]
HOLD_PKGS = [
'bsdpan-*',
]
MAKE_ARGS = {
‘editors/vim’ => ‘-DLITE CONF_OPT_MULTIBYTE=–enable-multibyte’
}
BEFOREBUILD = {
}
AFTERINSTALL = {
# Re-enable the X wrapper
‘x11-servers/XFree86-4-Server’ => sprintf(
‘cd %s/bin && if [ -x Xwrapper-4 ]; then ln -sf Xwrapper-4 X; fi’,
x11base()),
}

PKG_SITES = [
sprintf('ftp://freebsd.csie.nctu.edu.tw/pub/FreeBSD/ports/i386/packages-stable/'),
]
PORTUPGRADE_ARGS = ENV['PORTUPGRADE']
○ 使用pkgtools自動化升級應用程式
如果於pkgtools.conf中有設定在執行portupgrade之前,先更新ports tree,則以
有權限安裝應用程式的使用者,編寫crontab:
0 6 * * 1 /usr/loca/sbin/portsdb –Uu && /usr/local/sbin/portupgrade –a
若沒有於pkgtools.conf中有設定在執行portupgrade之前,先更新ports tree,則
以有權限安裝應用程式的使用者,編寫crontab:
0 6 * * 1 /usr/local/bin/cvsup –g –L 2 /usr/share/examples/cvsup/ports-supfile &&
/usr/local/sbin/portsdb –Uu && /usr/local/sbin/portupgrade –a
另外,在傳統自動化升級的方式,可使用pkg_version –c的方式,而在portupgrade
則以portversion –c方式取代。
0 6 * * 1 /usr/local/bin/cvsup –g –L 2 /usr/share/examples/cvsup/ports-supfile &&
/usr/local/sbin/portsdb –Uu && /usr/local/sbin/portversion –c >! /tmp/update_apps
&& sh /tmp/update_apps
注意:
在相同應用程式安裝兩套版本時,欲將其中舊版本強制刪除,而以新版本取代其
作用時,務必先確定其來源皆來至同一ports。
例如:發現在系統中安裝了兩個版本的gettext
gettext-0.10.35_2 GNU gettext package
gettext-0.11.2 GNU gettext package
先檢查是否來自同一ports。
Port: gettext-0.11.1_3
Path: /usr/ports/devel/gettext
Info: GNU gettext package
Maint: portmgr@FreeBSD.org
Index: devel

B-deps: bison-1.35_1 expat-1.95.2 libiconv-1.7_5 libtool-1.3.4_3
R-deps: expat-1.95.2 libiconv-1.7_5
Port: gettext-0.10.35_2
Path: /usr/ports/devel/gettext-old
Info: GNU gettext package
Maint: portmgr@FreeBSD.org
Index: devel
B-deps: libtool-1.3.4_3
R-deps:
由結果可知,這兩個版本皆有不同的相依性軟體,且來自不同的ports,因此不
可將其中一個取代另一個的功能,否則相依的應用程式可能會發生錯誤。
參考文件
pkgtools manual
freebsd diary article – clean ports
勘誤
2002-07-04 v0.1 beta
2002-07-18 v1.0
2002-08-16 bug-fixs – v1.1
2002-09-18 pkgtools updated, changelog – v1.2
編者
元智大學資訊管理學系 曾義峰 ( s882617@mail.yzu.edu.tw )

去小恶魔学园没找到, 只好自己翻译一下, 和原版有些出入, 加上一些自己的理解, 有误还请指出
英文原版file:///usr/share/doc/en/books/handbook/makeworld.html

注意事项

* 备份系统, 备份一下总不至于吃亏
* 订阅对应邮件列表, 希望你的英文不至于太差, 在对应邮件列表上贴上你问题的描述, 描述清楚出现的问题及受影响的系统

STABLE: freebsd-stable@FreeBSD.org
CURRENT: freebsd-current@FreeBSD.org

升级步骤(假设你已经同步到要升级的代码)

1. 读一下/usr/src/UPDATING, 上面由一些你可能需要注意的事项, 一定要读一下, 但并不代表这一定比从邮件列表上得到的信息有用, 所以推荐订阅邮件列表
2. 检查/etc/make.conf, 查看/etc/make.conf和/etc/default/make.conf的不同之处, /etc/default/make.conf中包含一些缺省定义, 不过大部分都被注释掉了, 可以考虑把它们加入到/etc/make.conf中, 不过要记得/etc/make.conf所有的make命令都起作用
3. 更新/etc下的文件, /etc下存放配置和启动脚本, 有些文件在不同的版本中是不同的, 所以需要进行更新, 从FreeBSD 开始可以在编译前使用命令 mergemaster 加上 -p 选项. 它将检查为了正常运行buildworld和installworld而需要更新的文件, 命令如下:

# cd /usr/src/usr.sbin/mergemaster
# ./mergemaster.sh -p

4. 进入单用户模式, 避免多用户系统带来的文件升级不成功问题, 还有一种方法就是在多用户模式下编译, 单用户下升级安装, 命令如下

# shutdown now

重启后使用boot -s 进入单用户模式

# fsck -p
# mount -u /
# mount -a -t ufs
# swapon -a

加入升级前系统使用本地时间而没有使用GMT, 必须打入命令

# adjkerntz -i

调整时区等设置, 保证系统的正常安装
5. 移除/usr/obj

# cd /usr/obj
# chflags -R noschg *
# rm -rf *

6. 编译
a 保存编译输出, 注意不要存在/tmp目录下, /tmp下的文件可能在重启后被清除

# script /var/tmp/mw.out
Script started, output file is /var/tmp/mw.out
# make TARGET
… compile, compile, compile …
# exit
Script done, …

b 编译

# cd /usr/src
# make -j4 -DNOPROFILE buildworld #或者在/etc/make.conf加上NOPROFILE=true

FreeBSD 2.2.5后make world分成make buildworld和make installworld, 注意这里只作make buildworld
c 耗时: PIII500/128M RAM大约需要2个钟头左右
7. 编译安装新内核

# cd /usr/src
# make buildkernel
# make installkernel

编译使用GENERIC配置的内核, 推荐编译一个, 以免以后编译内核后无法使用新内核启动没有make installworld前定制编译新内核使用下面的命令

# /usr/obj/usr/src/usr.sbin/config/config KERNELNAME

8. 以新内核重启到单用户模式
9. 升级系统, 注意要使用和make buildworld使用的-D选项, 并且绝对不能使用-j选项

# cd /usr/src
# make installworld

假如编译时:

# make -DNOPROFILE=true buildworld

安装时就应该:

# make -DNOPROFILE=true installworld

10. 升级那些没有被make world升级的文件, 如/etc下的文件, 可以使用mergemaster或者手工升级, 这一点请参见mergemaster的手册, 在升级前建议备份/etc目录.
11. 更新/dev 通常使用mergemaster, 就会重建/dev, 或使用命令 sh MAKEDEV 建立
12. 更新/stand

# cd /usr/src/release/sysinstall
# make all install

13. 再次重启

# fastboot

14. 结束升级, 加入有些程序无法运行的话可以重新编译安装, 例如

# cd /usr/src/usr.bin/file
# make all install

2004年08月04日

Emacs 提供了一个功能齐全的 CVS 界面 PCL-CVS,使得 CVS 的工作基本可以单
键完成,此外,Emacs 的 VC 也非常方便。下面简单介绍 PCL-CVS 的使用,之后再
简要介绍 VC 的方便之处。

1. 当然,先用命令行 check out 出源码拷贝

      $ cd ~/work
      $ cvs -d :pserver:user@host:/path/to/repository co MODULE

2. 从 Emacs 开始

   几个命令都可以进入 PCL-CVS 中,例如用 cvs-examine:

      M-x cvs-examine RET path/to/MODULE RET

   RET 表示回车键;path/to/MODULE,源码复本的目录,cvs-examine 缺省为当前
   目录。此时 Emacs 打开名为 *cvs* 的缓冲,就是 PCL-CVS 的主界面。

   PCL-CVS 只是命令行 cvs 的前端界面。在 *cvs* 缓冲中的命令,基本只需要按
   一两下键盘,Emacs 将其翻译为 cvs 控制命令。每执行一次,Emacs 会在缓冲
   底部显示对应的 cvs 命令,以供参考。

3. 在 cvs 缓冲中常用的命令

   n, p   移动光标。

   f, o, RET 打开当前文件。

   M-s    列出所有文件的当前状态。
   x      在缓冲中去掉所有是 Up-To-Date 的状态的文件,这样比较干净。

   M-u    更新本地拷贝。

   U      放弃所做的改动,小心别把你没有提交的工作弄没了。

   m      标记文件,用于对多个文件同时操作。u 去掉标记并下移;Backspace
          去掉标记并上移;M-Backspace 同时去掉 buffer 中所有标记。% 用正
          则表达式标记文件。

   c      准备提交所做的改动,会弹出一个 *cvs-commit* 缓冲,用来写修改的
          日志,写完完按 C-c C-c,执行提交。如果有标记,同时对所标记的所
          有文件相库提交。

   C      和 c 类似,但是清除上次提交时留在 *cvs-commit* 缓冲中的内容,不
          过如果当前目录里的 ChangeLog 文件中有相关内容,会自动插入。

   d      有一个提示,询问用哪种方式 diff。此时常用的可能是:

          d d  或 d =,比较文件,本地拷贝和最后一次提交时的修订版;
          d h  比较本地拷贝和当前源码库中最新版;
          d b  比较本地拷贝和该文件的备份;
          d e  用 ediff 比较文件,本地拷贝和最后一次提交时的修订版。
  d y  和前一天的比较

   r      删除文件,从当前拷贝的工作目录中删除,需要提交。

   a      添加文件,添加到当前拷贝的工作目录中,需要提交。

   i      把某个文件的名字添加到 .cvsignore 文件,这样在运行 cvs 命令时,
          cvs 不再理会此文件。编辑 .cvsignore 文件,每一行一个或一类文件。
          下面是一个 .cvsignore 文件的例子。有些类型的文件 cvs 缺省就是忽
          略的,比如 .o 文件。

   t      设置 tag,提示输入 tag 名字。

   l      查看一个文件,所标记的多个文件,或目录文件的 log 信息。

   s      通过 cvs status 命令查看文件或目录的状态,会弹出一个漂亮的
          *cvs-info* 缓冲,列出文件的状态信息。

   z, q   关闭 *cvs* 缓冲。

4. cvs buffer 中几种状态的说明(括号中是此时可能需要用到的命令):

   cvs buffer 中按一下 M-s 可以列出所有文件。每个一行,分别列出了当前的
   CVS 状态、修订版和文件名。

   “Up-to-date” 文件和库中文件一致,也就是说,目前是最新的修订版,而且没
   有被改动过。(按 f 或 RET,进入文件进行编辑,l 看修改历史,+ 看 tag 信
   息)

   “Need-Update” 文件相对于源码库,不是最新的,需要更新。(M-u 更新,d h
   比较当前文件和源码库中的区别)

   “Modified” 文件已经被改动过,但还没有提交到源码库。(c/C 提交,d d 比
   较,d e 用 ediff 比较,U 放弃修改,小心使用)

   “Added” 用 cvs add 命令新添加的文件,添加了新文件只在本地有效,需要提
   交到源码库。(c/C 提交)

   “Removed” 用 cvs 的 remove 命令删除的文件,同 add 一样,需要提交到源码
   库。(c/C 提交)

   “Needs-Merge” 你编辑文件的时候,别人又向源码库提交过,因此本地的改动,
   和源码库中的需要合并。(先 M-u 更新,如果发生冲突,手工修改,再 c/C 提
   交,d b 和原来的备份比较,d h 和库中比较)

   “Conflict” 你的提交和源码库中当前的状态有冲突,需要手工修改,并再提交
   一次。(手工修改,再 c/C 提交)

   “Unknown” 源码库中没有该文件,这或许不是你想要的,或许是刚刚新建的。
   (如果想让 cvs 忽略此文件,按 i;想添加到源码库,按 a,再提交;用 r 删
   除)

   “Missing” 源码库中有,可是本地拷贝中却没有了。(M-u 更新,可以从新从源
   码库得到拷贝)

5. 用 Emacs 的前缀参数修改 cvs 命令的选项

   很多 cvs 命令可以给一个前缀参数,改变缺省的行为。多数的前缀参数都是
   C-u,而多数改变的行为,就是修改传递给 cvs 的默认选项。

   每执行一次操作,pcl-cvs 的 *cvs* 缓冲底部都会显示实际执行的 cvs 命令,
   这些命令往往带有一些参数,如何修改这些参数呢?就通过给 pcl-cvs 的命令
   加前缀 C-u。一般的,一个 C-u 只改变当前命令所用的 cvs 选项,如果前缀两
   个 C-u,则是永久改变所用选项。

   例如,d d 缺省比较当前拷贝和库中你check out时的修订版。

       如果用 C-u d d 会提示输入 cvs 的选项,此时你可以给任意的 cvs diff
       选项,用以进行各种各样灵活的比较。比如,输入 -r1.10 -r2.3 RET,此
       次比较的就是源码库中当前文件修订版 1.10 和 2.3 之间的区别。

       如果 C-u C-u d d,输入 -r1.10 RET,以后的 d d 命令都会带着 -r1.10
       仿佛永久修改了默认选项。当然,可以再 C-u C-u d d 修改回去。

   再如,cvs add 命令添加二进制文件需要 -kb 选项,用 C-u a 则提示输入cvs
   add flags,输入 -kb RET,OK。

6. 查看一些信息

   在一个文件或目录上,或标记了一些文件,按 l 可以在 *cvs-info* 缓冲中看
   到这些文件的 log 信息,就是提交到源码库中的更新日志;按 s 可以看到状态
   信息;按 + 也是状态信息,但是 tag 表为树型结构。

   按 l 查看 log 信息时,*cvs-info* 缓冲的状态为 (Log-View CVS)。此时,有
   很多方便的操作,比如比较两个修订版之间的不同,修改源码库中的 log 信息,
   打开某个文件任意的修订版。比如,在 *cvs* 的某个目录上面按了 l,然后转
   到 *cvs-info* 缓冲中,这里面列出的时该目录中所有文件的 log 信息,此时
   的常用命令如下。

       n, p    移动光标,在一个文件内的不同修订版之间
       N, P    移动光标,在不同的文件之间,M-n, M-p 同样

       m       设置 mark
       d       和设置 mark 的那个修订版进行 diff

       e       修改当前 log,编辑完,C-c C-c 提交

       f, o, RET
               这几个都是打开当前的修订版,稍有区别。用 f 的时候如果提示
               vc-find-version 没有定义,手工加载一下 vc 库
               M-x load-library RET vc RET。

       z       关闭该缓冲

   如果在 *cvs* 的目录里按 s,此时的 *cvs-info* 缓冲为(CVS-Status CVS)状
   态,在这个缓冲中,也可以做类似的一些操作:

       N, P   在文件之间移动, M-n, M-p 同样
       n, p   上一行,下一行

       f, o, RET
              把光标移动到某个 tag 的名字上,则可以直接打开那个 tag 所在
              的修订版

       T, t   把每个文件所列的 tag 表转为树型结构,T 为横向的树,t 为竖向
              的树

   diff 命令产生的 *cvs-diff* 缓冲中也类似,N/P 在文件之间移动,n/p 在不
   同的 diff 之间移动。此外,在任何一行代码的未知按 o 或 RET 可以直接转到
   文件中的实际未知,很方便的。

7. Emacs 的 VC 的方便之处

   在 PCL-CVS 中,几乎可以做任何 CVS 相关的操作。但有时候未免有些麻烦,配
   合 Emacs 的 VC (Version Control) 会方便很多。

   Emacs 的 VC 模式的作者就是著名的 Eric S. Raymond。VC 的功能很强大,而
   且方便灵活。可以使用在三种版本管理系统中:RCS、CVS、SCCS,操作方式一致。
   和 PCL-CVS 不同的是,VC 使用 C-x v 前缀完成大部分功能,不像PCL-CVS 使
   用一个主界面,这使 VC 显得更方便。

   几个主要的命令:

   C-x v v    vc-next-action
              顾名思义,执行下一个动作,下一个动作是什么就执行什么,如果
              是 Unknown 就 cvs add,如果是 Modified 就 commit,如果是
              Up-to-date 就什么都不用做了。最方便的是只需在当前 buffer 中
              执行。

   C-x v m    vc-merge
              将库中别人所做的改动与本地的改动合并,和库中的版本保持一致。

   C-x v a    vc-update-change-log
              更新更改日志文件 ChangeLog。如果源码库或本地拷贝中还没有,
              试一下这个,它会根据 cvs 的提交日志,自动产生 ChangeLog,如
              果已经有了,但已经有一段时间没有更新过,它会自动更新
              ChangeLog 文件到最新的一条记录。

   C-x v ~    vc-version-other-window
              PCL-CVS 也可以方便的查看某个历史版本,不过都需要转到相应的
              控制界面(*cvs* 或 *cvs-info* buffer)中。而 VC 的这个命令可
              以在当前缓冲中用,会提示输入版本号,然后显示在另一个窗口中,
              并保存在当前目录,文件名为 FILENAME.~REV~。

   有时候,用 CVS 管理的东西不需要整体的控制,比如自己的笔记、随笔之类,
   用 Emacs 设置上 bookmark,打开就写点,写完马上就提交,往往不必打开
   PCL-CVS,恰恰 VC 这些灵活的命令非常合适。

   继续了解 VC:

   C-x v =    vc-diff
              比较文件。如果用了前缀参数,会询问和哪个文件的哪个版本比较。

   C-x v u    vc-revert-buffer
              放弃没有提交的改动,恢复原状,也就是你的本地拷贝的版本,并
              不管库中的最新改动。如果想同时和库中别人所做的改动保持一致,
              用 C-u 作为前缀参数。

   C-x v g    vc-annotate
              看看你的每行代码的状态(编辑历史)。每行的颜色用来表示这行代
              码的新旧程度,蓝色的时间最长,红色的最短,其他的居中。默认
              的最长时间为一年,超过一年的都显示为蓝色。用前缀参数可以修
              改所显示的版本和默认最长时间。

              这个缓冲中还有一些有趣的功能,可以直接转到某个修订版。每行
              的最前面为当前行最后一次修改的修订版,在这行上按 J,整个缓
              冲中的内容全都替换为这个修订版;按 N (或 P) 为缓冲中当前的
              后一个(前一个)修订版;按 A 转到当前行上次被修改的版本。N/P
              按修订版历史浏览,A 按当前行修改历史浏览,J 跳转该行所指修
              订版,W 回到该文件的当前修订版。注意,模式行上文件名的后面
              标注了缓冲当前内容的修订版。另外,D 可以比较当前行上的修订
              版和前一修订版的区别,N/P 可以使用前缀参数。

   C-x v d    vc-directory
              打开一个带版本控制功能的 Dired buffer,功能和 pcl-cvs 的
              *cvs* buffer 有些类似。或许对非 CVS 的版本管理比较有用。

8. 相关配置

   由 CVS 管理的模块中都有 “CVS” 目录,打开 cvs-dired-use-hook 时,在
   “CVS” 目录上按 F,直接进入该模块的 *cvs* buffer:
     (setq cvs-dired-use-hook ‘always)

   给 cvs-examine 一个方便的绑定:
     (define-key global-map “\C-xve” ‘cvs-examine) 绑定到 C-x v e。

* 正则表达式语法

      正则表达式(regular expressions, 缩写为regexp)是由几个特殊字符和一些普通
  字符组成,一个普通字符就是一个简单的正则表达式,仅仅可以匹配与自己相同的字
  符。而特殊字符包括“$”,“^”,“.”,“*”,“+”,“?”,“[”,“]”以
  及“\”。除非在一个字符前面有“\”,否则正则表达式中出现的任何其他字符都是
  普通字符,(当你在 Lisp 程序中使用正则表达式时,每一个“\”都必须写成两个,,
  因为需要对字符串中的“\”转义,请看下面的例子。)

      例如,“f”不是特殊字符,是普通字符,因此“f”是一个正则表达式,它仅仅
  匹配串“f”。(不匹配“ff”。)同样“o”是仅匹配串“o”的正则表达式。(当不
  区分大小写时,前面的两个式子也匹配“F”和“O”,而实际上,一般认为它们是
  “同样的串”,并不是因为例外。)

      两个任意的表达式 A 和 B 可以连接,其结果是能够匹配以 A 开始,其余部分是
  B 的字符串的表达式。

      举个简单的例子,我们将表达式“f”和“o”连接,得到表达式“fo”,仅匹配
  串“fo”,很简单的。想做些不简单的,需要使用特殊字符。下面介绍这些特殊字符。

** 特殊字符

*** “. (Period)”

      匹配除了换行符(newline)之外任何单个字符的特殊字符。通过“连接”,可以得
      到如“a.b”的表达式,匹配所有的以“a”开始,以“b”结束的三个字符的字符
      串。

*** “*”

      自身不构成表达式的部分,作为后缀操作符,表示某个前导表达式可以任意次重
      复。比如,“o*”匹配任意个“o”连成的串(包括空串)。

      “*”总是作用于“最少的”可能的前导表达式。于是,“fo*”中,可以重复的
      是“o”,而不是“fo”,匹配形如“f”, “fo”, “foo”的串等等。

      匹配程序以迅速且尽可能多的找到重复部分来处理带“*”的结构。然后继续其他
      部分的处理。如果失败了,为了使剩余的部分能够尽可能的匹配,匹配程序会回
      退,释放一些已经由“*”匹配的结构。例如,在使用“ca*ar”来匹配串
      “caaar”时,“a*”首先试图匹配全部的三个“a”;但余下的部分是“ar”,
      不能匹配“r”,失败;接着选择是用“a*”匹配两个“a”,成功。

*** “+”

      和“*”相似的后缀操作符,它表示前导表达式至少出现一次。例如,“ca+r”匹
      配串“car”和“caaaar”,但不能匹配“cr”,然而“ca*r”却可以。

*** “?”

      也是一个和“*”相似的操作符,它表示前导表达式至多出现一次。例如,
      “ca?r”仅仅匹配“car”或“cr”。

*** “*?, +?, ??”

      是前面几个操作符的非贪心(non-greedy)的变体。正常的“*”, “+”, “?”
      操作符是“贪心的(greedy)”,只要总体上能够匹配,这些操作符总是尽可能多
      的匹配。当紧跟着“?”时,则是非贪心的:将尽可能少的匹配。

      “ab*”和“ab*?”都能匹配串“a”和“abbbb”;但如果你试图用它们来匹配
      “abbbb”时,“ab*”将匹配全部(最长有效匹配),而“ab*?”将仅仅匹配
      “a”(最短有效匹配)。

*** “\{N\}”

      指定重复次数为 N 的后缀操作符,前导表达式必须恰好出现 N 次。例如
      “x\{4\}”仅匹配串“xxxx”。

*** “\{N,M\}”

      指定重复次数在N和M之间的后缀操作符,就是说它的前导表达式的出现次数至少
      是N 但不能超过 M。如果省略 M,表示没有上限,但它的前导表达式至少出现 N
      次。“\{0,1\}”等于“?”。“\{0,\}”等于“*”。“\{1,\}”等于“+”。

*** “[ ... ]”

      字符集,以“[”开始以“]”结束。最简单的例子,在两个方括号中间的字符就
      是这个集合所能匹配的全部。

      所以,“[ad]”仅匹配一个“a”或一个“d”,“[ad]*”匹配所有仅由“a”和
      “d”构成的串(和空串)。“c[ad]*r”匹配“cr”,“car”, “cdr”,
      “caddaar”,等等。

      也可以用一个“-”放在一个开始字符和一个结束字符的中间,表示字符集中字符
      的范围。“[a-z]”匹配所有小写 ASCII 字母。范围可以和单独的字符自由的组
      合在一起,比如“[a-z$%.]”,匹配了任意的小写字母,或“$”,“%”,以及
      “.”。

      注意,通常在字符集中的特殊字符不再特殊,而在字符集中的“]”,“-”和
      “^”却是特殊字符。

      如果想在字符集中包括字符“]”,必须放在第一个字符位置。例如,“[]a]”匹
      配“]”或“a”。想包括“-”,要在第一个或最后一个位置,或在一个范围的后
      面,如“[]-]”匹配“]”和“-”。

      如果想在字符集中包括字符“^”,不可以放在第一个位置。(在开始位置,它会
      把这个字符集取补——看下面。)

      当不区分大小写使用范围时,表示范围的两个字符或者都是大写、或者都是小写、
      或者都不是字母。混合大小写的范围如“A-z”意思不明确,不被接受,或许在将
      来的 Emacs 中会被改变。

*** “[^ ... ]”
      “[^”表示“补集合”,匹配的字符是除掉指定的字符外其他所有的字符。如,
      “[^a-z0-9A-Z]”匹配除掉ASCII字母和数字的所有字符。

      当“^”在字符集中第一个时,被看作是特殊字符。而跟在“^”后面的字符被看
      作是第一个字符(就是说,此处的“-”和“]”将不是特殊的)。

      一个补集合可以匹配换行符,除非换行符被指定为补集合中的一个字符。这不同
      于某些象“grep”的程序对正则表达式的处理。

*** “^”
      仅仅匹配在文本中行首的那个空串的特殊字符。就是说,“^foo”匹配在行首的
      “foo”。

*** “$”
      和“^”相似,但仅匹配行尾的空串。因此“x+$”匹配在行尾的一个或多个“x”
      的串。

*** “\”
      有两个作用:引用特殊字符(包括“\”);产生附加的特殊结构。
     
      因为“\”引用特殊字符,“\$”是一个仅匹配“$”的表达式,“\[”是一个仅
      匹配“[”的表达式,等等。

** 关于反斜线
      注意:为考虑兼容性,如果在其没有意义的上下文中,特殊字符将被当作普通字
  符。比如:“*foo”中把“*”当作普通字符,因为在它前面没有可以作用的前导表达
  式。很少有人会根据这条规则去实践;无论如何,在任何地方都加上引用会更好些。

      对于大多数情况,“\”后接任何字符仅仅匹配那个字符。然而,有几个例外:
  以“\”开始的两字符序列会有特殊的意思。其中的第二个字符往往是普通字符。下
  面是“\”的结构表。

*** “\|”
      指定一个选择。中间有一个“\|”的两个正则表达式 A 和 B,形成了一个可以匹
      配 A 或 B 的文本。它首先试图用 A 匹配,如果失败再用 B 去试。

      由此,“foo\|bar”仅匹配“foo”或“bar”。

      “\|”作用于两边最长的可能的表达式。仅由“\( ... \)”括起来才可以限制
      “\|”的分组能力。

      Emacs 有全面的回退功能,以处理“\|”的多种的用途。

*** “\( ... \)”
      分组结构,有三个功能:

1.围住“\|”的选择项,以实现别的操作。例如“\(foo\|bar\)x”匹配
          “foox”或“barx”。

2.围住复杂的表达式以实现后缀操作符(如“*”“+”和“?”)的操作。例如
          “ba\(na\)*”匹配如“bananana”等,有任意个(零或更多)的“na”串。

3.记录一个已匹配的子串用作后面的参考引用。

      最后一个应用并不是括号的分组功能思想的结果;这个分开的特点是给同样的
      “\( ... \)”结构赋予的第二种含义。在实际应用中,这两种含义通常不会发生
      冲突。当发生冲突的时候,可以使用“谨慎的”分组("shy" group)。

*** “\(?: ... \)”
      “谨慎的”分组("shy" group),这个分组不记录匹配的子串;你不能用“\D”来
      引用。这在机械的结合正则表达式的时候有用,这样,你可以为语法目的加入分
      组,而不用干涉使用者写的分组的个数。

*** “\D”
      匹配和“\( ... \)”结构第 D 次出现时所匹配的同样的文本。

      在“\( ... \)”结构结束之后,匹配程序保存被这个结构匹配的文本(的开始和
      结束);之后的正则表达式中,你可以使用“\”跟着一个数字 D 来表示“匹配
      和‘\( ... \)’结构第 D 次出现时所匹配的同样的文本。”

      正则表达式中前九个出现的“\( ... \)”结构,按正则表达式中左括号出现的次
      序从 1 到 9 赋值。因此可以用“\1”到“\9”来引用相应的“\( ... \)”结构。

      例如,“\(.*\)\1”匹配任何有完全相同的两部分而无换行符的串。“\(.*\)”
      匹配前一半,可以是任意的串,“\1”匹配后面的,但必须和前面的完全相同。

      如果一个特定的“\( ... \)”结构匹配了多次(比如后面有一个“*”,这很显
      然),那么仅记录最后一次的匹配。

*** “\`”
      匹配空串,但仅是接在缓冲区的开始处的。

*** “\'”
      匹配空串,但仅是接在缓冲区的尾部的。

*** “\=”
      匹配空串,但仅在“点(point)”处的。

*** “\b”
      匹配空串,但仅在一个词的开始或者结尾的。例如,“\bfoo\b”匹配任何作为单
      独的词出现的“foo”。“\bballs?\b”匹配作为单独的词出现的“ball”或
      “balls”。

      在缓冲区的开始和结束位置时,“\b”不考虑紧接其前的文本是什么。

*** “\B”
      匹配空串,但不在词的开始或结尾处。

*** “\<”
      匹配空串,但仅在词的开始处。仅当一个构成词的字符在缓冲区开始处时“\<”
      匹配缓冲区开始处的空串。

*** “\>”
      匹配空串,但仅在词的结尾处。仅当缓冲区尾部有构成词的字符时“\>”匹配缓
      冲区尾部的空串。

*** “\w”
      匹配任何构成词的字符。由语法表决定这些字符是什么。

*** “\W”
      匹配任何非构成词的字符。

*** “\sC”
      匹配任何语法是 C 的字符。这里 C 是一个指定特定语法类的字符:如“w”为词
      的构成字符,“-”或“ ”为空白,“.”为普通标点符号,等等。

*** “\SC”
      匹配任何字符不属于语法 C。

*** “\cC”
      匹配任何属于种类 C 的字符。例如,“\cc”匹配汉字,“\cg”匹配希腊字符等。
      如果想了解已知种类,用“M-x describe-categories ”。

*** “\CC”
      匹配所有不属于种类C的字符。

    属于词和语法的结构是由语法表的设置来控制的。

** 例
        下面是一个复杂的正则表达式,存储在“sentence-end”,Emacs 将其用于识
    别句子的结束以及后面的任何空白。其中以 Lisp 语法区分了空白符和制表符。在
    Lisp 语法中,串常量用双引号括起来。“\"”表示双引号是表达式的一部分,
    “\\”表示反斜扛是表达式的一部分,“\t”表示制表符,“\n”表示换行。

         "[.?!][]\”‘)]*\\($\\| $\\|\t\\|  \\)[ \t\n]*”

    其中包含四个连续的部分:匹配句号(“.”)、“?”或“!”的字符集;匹配右方括
    号、右(单/双)引号的字符集的任意次重复的部分;在“反斜线括号”部分中,匹配
    行尾、行尾空白、制表符或两个空格的可选集合;以及一个任意次匹配空白的字符
    集。

        在增量搜索中,要用 TAB 输入制表符,“C-j”输入换行符。也可以使用单
    独的反斜线,不用象 Lisp 串中那样写成两个。