<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[^00企鹅的家^]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[恩恩，欢迎来到00企的空间，别闲着，随便看 :)]]></description>
<link>http://hi.baidu.com/00%C6%F3%B6%EC</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[转：Image Magic 速查]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/ae57e6c64ab215119c163d45.html]]></link>
        <description><![CDATA[
		
		<h1 >Image MagicK 速查</h1>


<div class="menu">
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/index.html">Home</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/academic/index.html">Academic</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/computing/index.html">Computing</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/wiki/index.html">GNU Notes</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/server/index.html">DSEC Server</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/journal/index.html">Wild Journal</a></div>
<div class="menuitem"><a href="http://dsec.pku.edu.cn/~yuhj/photos/index.html">Photos</a></div>
</div>

<div >
<div > </div>
</div>

<p><a href="file:///C:/Documents%20and%20Settings/Tropic%20Tux/桌面/Image%20MagicK%20速查.files/magick.png"><img src="file:///C:/Documents%20and%20Settings/Tropic%20Tux/桌面/Image%20MagicK%20速查.files/magick.png"></a> Image MagicK 是一个强大的图象处理工具包。它提供了几个非常方便的命令行命令: display, animate,import, montage,mogrify,identify等，可以进行图象的显示，缩放，旋转，调色，加框，加注释等，还能制作GIF动画，图象索引，能自动生成图象.</p>
<ol>
    <li>制作索引图和动画
    <pre class="example">!/bin/bash
montage -bordercolor red -borderwidth 3 -label &quot;%f&quot; -tile 5x3 *.JPG montage.jpg
mogrify -format gif *.JPG
display montage.jpg
animate *.JPG</pre>
    </li>
    <li>缩放 <exmaple></exmaple>convert -sample 80x40 input.jpg output.jpg #注意：缩放后图像保持原来的长宽比例 convert -sample 25%x25% input.jpg output.jpg</li>
    <li>为当前目录的所有图像生成缩略图
    <pre class="example">for img in `ls *.jpg`
 do
   convert -sample 25%x25% $img thumb-$img
 done</pre>
    </li>
    <li>获取文件信息 libtiff
    <pre class="example">tiffinfo filename.tiff
pnginfo filename.png</pre>
    </li>
    <li>可以使用 <a href="http://dsec.pku.edu.cn/~yuhj/wiki/ImageMagick.html">ImageMagick</a> 的 identify
    <pre class="example">identify -verbose sample.png 
 identify -format &quot;%wx%h&quot; sample.png</pre>
    </li>
    <li>旋转图像
    <pre class="example">convert -rotate 90 input.jpg output.jpg</pre>
    </li>
    <li>更改文件类型
    <pre class="example">convert input.jpg output.png</pre>
    </li>
    <li>为图像增加注释文字
    <pre class="example">convert -font helvetica -fill white -pointsize 36 \
 -draw 'text 10,50 &quot;Floriade 2002, Canberra, Australia&quot;' \
 floriade.jpg comment.jpg 
convert -font fonts/1900805.ttf -fill white -pointsize 36 \
 -draw 'text 10,475 &quot;stillhq.com&quot;' \
 floriade.jpg stillhq.jpg</pre>
    </li>
    <li>特殊效果
    <pre class="example">convert -charcoal 2 input.jpg output.jpg #炭笔
convert -colorize 255 input.jpg output.jpg #着色 可以指定三种颜色 red/green/blue
convert -implode 4 input.jpg output.jpg  #内爆效果
convert -solarize 42 input.jpg output.jpg #曝光，模拟胶片曝光
convert -spread 5 input.jpg output.jpg  #随机移动，参数是位移大小</pre>
    </li>
    <li>一次执行多个操作
    <pre class="example">convert -sample 25%x25% -spread 4  -charcoal 4 input.jpg output.jpg</pre>
    </li>
</ol>
<h2><span class="toplink"><a href="http://dsec.pku.edu.cn/~yuhj/wiki/ImageMagick.html#top">top</a></span><a href="http://dsec.pku.edu.cn/~yuhj/wiki/ImageMagick.html">ImageMagick</a> FAQ 摘要</h2>
<ol>
    <li>如何让animate在显示图片的过程保持窗口的标题不变
    <pre class="example">animate -title &quot;My Image Sequence&quot; images.</pre>
    </li>
    <li>import抓得的图片与X服务器上显示的不一致怎么办？
    <pre class="example">import -descend image.miff</pre>
    </li>
    <li>如何动画显示YUV 图片序列?
    <pre class="example">animate -geometry 352x240 -scene 0-71 yuv3:frame%d</pre>
    </li>
    <li>如果只看一个RGB图片的红色通道(red channel)?
    <pre class="example">display -gamma 1.0,0.0,0.0 image.miff</pre>
    </li>
    <li>如何改变PostScript默认纸张大小?<br>
    要改变默认的612x792大小，修改magick/image.h中的<a class="nonexistent" href="mailto:yuhaijun@gmail.com">PSPageGeometry</a>的值并重编译.</li>
    <li>如何自左至右无边无框无文字半三幅画连接在一起？
    <pre class="example">convert +append image1.ppm image2.ppm image3.ppm side_by_side.miff
 # 或
convert -size 350x500 xc:black composite.miff
composite -geometry +0+0 composite.miff image1.gif composite.miff
composite -geometry +100+0 composite.miff image2.gif composite.miff
composite -geometry +0+300 composite.miff image3.gif composite.miff
composite -geometry +0+375 composite.miff image4.gif composite.miff</pre>
    </li>
    <li>如何生成gif动画?
    <pre class="example">convert -delay 20 frame*.gif animation.gif
convert -delay 20 frame1.gif -delay 10 frame2.gif -delay 5 frame3.gif animation.gif
convert frame1.gif -page +50+100 frame2.gif -page +0+100 frame3.gif animation.gif
convert -loop 50 frame*.gif animation.gif
convert +adjoin images.* frames%d.gif</pre>
    </li>
    <li>如果完整的显示PostScript图片？
    <pre class="example">display -page letter image.ps</pre>
    </li>
    <li>什么是图片目录？如何使用它们?
    <pre class="example">#图片目录（visual image directory ，VID）的创建：
   montage *.jpg directory.vid
   convert 'vid:*.jpg' directory.vid
#显示图片目录
   display directory.vid
   display vid:movie.mpg</pre>
    </li>
    <li>如果带框架保存一个窗口?
    <pre class="example">xwininfo -frame
import -frame -window ID window.miff</pre>
    </li>
    <li>图片以单一颜色（a solid color）显示，是怎么回事？ 图片被破坏，或含有值为0的matte层，试着:
    <pre class="example">display +matte image.miff</pre>
    </li>
    <li>出现 &quot;???? library is not available ...&quot;是怎么回事? 没安装相关的函数库。参见安装说明。</li>
    <li>如何查看图片不光滑层(matte channel)的值？
    <pre class="example">convert image.tiff image.matte
display -size 640x480 gray:image.matte</pre>
    </li>
    <li>运行&quot;Convert in.gif out.png&quot; 时显示 &quot;Invalid Parameter - out. 你运行的convert是windows的分区类型转换程序。</li>
    <li>如何在图片增加斜角?
    <pre class="example">#对图片边缘的处理共分四类。
 1）增加有色边
convert -bordercolor red -border 25x25 image.jpg image.gif
 2）加亮或变暗图片边缘，以增强3D效果
convert -raise 25 image.jpg image.gif
 3）在图片周围增加装饰性框架。
convert -mattecolor gray -frame 25x25 image.jpg image.gif
 4）在图片边缘增加升、降斜角
convert -mattecolor gray -frame 25x25+0+25 image.jpg image.gif
convert -mattecolor gray -frame 25x25+25+0 image.jpg image.gif</pre>
    </li>
    <li>用窗口管理器运行display失败了，怎么办? 用下列命令之一来确认display运行在一个交互环境中：
    <pre class="example">display logo:Untitled
display &lt; /dev/console</pre>
    </li>
    <li>将PostScript文件转换为其它格式时，如何改善文字的外观？
    <pre class="example">convert -density 288 -geometry 25% image.ps image.gif</pre>
    </li>
    <li>如何用2－3英寸高的文字注释一个图片? 先检查有无可缩放字体： xlsfonts -fn '*-0-0-0-0-*'　有则：
    <pre class="example">convert -font '-*-helvetica-*-*-*--300-300-*-*-*-*-iso8859-1' \
        -fill green -draw 'text 50,300 Magick' image.gif annotated.gif
# If you have the FreeType support built into ImageMagick,
# just increase your pointsize and/or density:
convert -font Helvetica -pointsize 100 -density 300 ...</pre>
    </li>
    <li>如何将gif文件分析为一系列的单个图片？
    <pre class="example">convert animation.gif frame%02d.gif</pre>
    </li>
    <li>用NetScape显示的图片，如何去掉周围的背景色？ <exmaple></exmaple>convert +page alpha.gif beta.gif</li>
    <li>如何用web安全的颜色（Web safe colors）创建GIF或PNG图片？
    <pre class="example">convert -map netscape: alpha.gif beta.gif</pre>
    </li>
    <li>为何Adobe Acrobat 2.1不能读<a href="http://dsec.pku.edu.cn/~yuhj/wiki/ImageMagick.html">ImageMagick</a>'s制作的PDF? 用 Acrobat 3.0或以上版本，来阅读这种经zip压缩的pdf，或制作PDF时不进行压缩。
    <pre class="example">convert +compress images.tiff image.pdf</pre>
    </li>
    <li>如何在图片上增加一个不光滑层(matte channel)?
    <pre class="example">convert image.gif -matte temp.miff
composite -compose CopyOpacity mask.xbm temp.miff transparent.gif</pre>
    </li>
    <li>在NT环境下如何用convert在图片上写字？
    <pre class="example">convert -font Arial -fill blue -draw &quot;text 10,10 'your text here'&quot; d:\test.tif png:d:\test.png
convert.exe -pointsize 18 -draw &quot;text 0,0 &quot;This is my text!&quot;&quot; C:\blank.gif c:\text.gif</pre>
    </li>
    <li>为何GIF文件比期望的大? 需要在编译源码时加 --enable-lzw 参数，来打开LZW压缩功能。</li>
    <li>为何JPEG文件比期望的大? 可能嵌入Exif或IPTC等&quot;profiles&quot;, 或者含有没压缩的thumbnails. 可以用命令行参数 +profile &quot;<em>&quot;或相关的API来将它们去掉。 </em>&quot;或相关的API来将它们去掉。</li>
    <li>如何从图片文件中抽取第一张图片？
    <pre class="example">convert &quot;Image.gif[0]&quot; first.gif</pre>
    </li>
    <li>如何创建一张空白图片？
    <pre class="example">convert -size 800x600 xc:&quot;#ddddff&quot; ltblue.ppm
convert -size 800x600 null:white white.ppm
convert in.png -threshold 100% black.ppm  #&lt;--与in.png同大小</pre>
    </li>
    <li>为何GIF文件比期望的大? 需要在编译源码时加 --enable-lzw 参数，来打开LZW压缩功能。</li>
    <li>为何JPEG文件比期望的大? 可能嵌入Exif或IPTC等&quot;profiles&quot;, 或者含有没压缩的thumbnails. 可以用命令行参数 +profile &quot;</li>
</ol>
<h2><span class="toplink"><a href="http://dsec.pku.edu.cn/~yuhj/wiki/ImageMagick.html#top">top</a></span>使用笔记</h2>
<ol>
    <li>把matlab中画出的多幅图作成GIF动画
    <pre class="example">for i in `ls *.jpg`; do convert -trim -resize 350x305 $i crop.$i; done
 convert -delay 10 -loop 3 crop.frame*.jpg string.gif
 rm crop.frame*.jpg</pre>
    </li>
    <li>生成png格式的email地址
    <pre class="example">convert -size 185x19 null:white email.png
convert -font monospace -fill black -pointsize 16  -draw 'text 4,14 &quot;youremail@yourdomain&quot;' email.png email.png 
convert -font monospace -fill blue -pointsize 16  -draw 'text 3,13 &quot;youremail@yourdomain&quot;' email.png email.png</pre>
    </li>
</ol>

<div class="navfoot"><hr>
<table width="100%" summary="Footer navigation" border="0">
    <colgroup><col width="33%"></col><col width="34%"></col><col width="33%"></col></colgroup>
    <tbody>
        <tr>
            <td align="left"><span class="footdate">Updated: 2006-09-18</span></td>
            <td align="center"><span class="foothome"><a href="http://dsec.pku.edu.cn/~yuhj/wiki/index.html">Index</a> </span></td>
            <td align="right"> </td>
        </tr>
    </tbody>
</table>
</div> <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/ae57e6c64ab215119c163d45.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/ae57e6c64ab215119c163d45.html#comment">查看评论</a>]]></description>
        <pubDate>2009-11-30  16:28</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/ae57e6c64ab215119c163d45.html</guid>
</item>

<item>
        <title><![CDATA[ABS notes (3)]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/a23a41584ee00f8b810a1846.html]]></link>
        <description><![CDATA[
		
		重要系统信息的获取<br>
1. CPU/系统 32/64位信息：<br>
(1). 在LINUX下怎样决断你的CPU是32位还是64位?<br>
打入下面的命令<br>
grep flags /proc/cpuinfo<br>
输出<br>
flags&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm nx lm<br>
<br>
如果找到lm, 则说明你的CPU是64位的. lm是long mode的意思.<br>
* Long Mode - 64位CPU<br>
* Real Mode - 16位CPU<br>
* Protected Mode - 32位CPU<br>
<br>
(2). Linux下判断你是32系统还是64位系统.<br>
打入下面的命令<br>
uname -a<br>
输出1<br>
Linux test-1 2.6.18-92.el5 #1 SMP Tue Apr 29 13:16:12 EDT 2008 i686<br>
i386, i686说明你是32位的内核, 跑的是32位的系统.<br>
输出2<br>
Linux test-2 2.6.18-92.el5 #1 SMP Tue Apr 29 13:16:15 EDT 2008 x86_64<br>
x86_64则说明你是64位内核, 跑的是64位的系统.<br>
<br>
如果你cpuinfo的输出有lm标志, 而uname -a命令的输出是i386或i686, 说明你是64位的CPU跑的32位的系统. <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/a23a41584ee00f8b810a1846.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/a23a41584ee00f8b810a1846.html#comment">查看评论</a>]]></description>
        <pubDate>2009-10-19  11:27</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/a23a41584ee00f8b810a1846.html</guid>
</item>

<item>
        <title><![CDATA[win7 的硬盘安装 （只能用pe启动电脑的情况下）]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/87800b5090d1376b853524b2.html]]></link>
        <description><![CDATA[
		
		本安装假设是用u盘启动至winpe中：<br>
1. 目标安装盘必须是ntfs的，安装前可以先格好，假设目标盘是C盘<br>
2. 把os\win7里面的“bootmgr”“boot”&quot;efi&quot;文件夹都复制到C盘根目录下，并在C盘根目录下建个sources文件夹，把的os\win7\sources下的boot.wim复制到C盘下sourse文件夹 <br>
3. 管理员方式运行 --〉cmd--〉c:\boot\bootsect.exe /nt60 c:&#160; <br>
4. 保证现在的mbr是只有windows情况下的mbr，可以用winpe中一个叫分区表修复工具，还是啥名儿？反正是“分区表”开头的一个工具，里面有重 建mbr的菜单项。运行一下，如果需要的话。―― 这很重要，这是要保证重启的时候，不用u盘，机器能从c盘所在的硬盘的mbr启动。使得这个盘对bios和windows来讲，是第一块儿硬盘。否则 windows7安装运行到分区的时候，会无法创建/识别分区。<br>
5. 把\os\win7整个文件夹拷贝到硬盘中某个盘，之后安装好使用。重启计算机，拔下装有winpe的u盘。会看到正在启动安装程序，加载boot.wim。这个过程可能比较长，视不同配置，请等待…… <br>
6. 安装程序启动，选择你要安装的语言类型，同时选择适合自己的时间和货币显示种类及键盘和输入方式。 <br>
出现“开始安装界面”，(注意！！！不点击“现在安装”)点左下角“修复计算机”(repair my computer)。 <br>
进入“系统恢复选项”，选择单选的第一个，再选择最后一项“命令提示符”(command prompt)，出现DOS窗口。<br>
<br>
-------- 以下别人说要做，但是我觉得，在后一步全格盘即可，我没做---------<br>
7. 删除C盘中的如下文件(如果有文件是隐藏的，删除前请运行attrib -r -h -s) <br>
del C:\efi <br>
del C:\bootmgr <br>
del C:\boot <br>
del C:\sources <br>
删除这些很重要，没删除的话等下不能成功重起引导不了系统完成安装。 <br>
-------- 以上别人说要做，但是我觉得，在后一步全格盘即可，我没做---------<br>
<br>
<br>
8. 现在可以输入安装命令了，输入X（你的安装文件所在盘）:\win7\sources\setup.exe后回车。然后就跟光盘启动安装一一样了。 <br>
9. 在安装过程中到选择分区那一步可以的话把目标盘格一下，（选下面的drive options）确保安装顺利进行。 <br>
10. 之后就正常了，直到输入激活码那一步，不用填，也不用联机激活。点下一步，直至安装结束。<br>
11. 激活，用\os\Win7Loadersamblg，解压 看说明既可，很傻瓜。<br>
12. 其他：关于ie8不能看flash，我安装了最新的adobe shockwave player 11.5和adobe flash player 10 activex ，但是发现还是偶尔能看，其他的浏览器倒是都能看了，但是却容易假死。直到我装上了搜狗浏览器，我晕，居然都好了，搜狗还有这功效？<br>
<br>
<br>
<br>
------------&#160; 其他情况下的安装参考，引子网络 --------<br>
<br>
64位安装也一样,不过需要32位的bootsect.exe,拷到c盘，c:\bootsect.exe /nt60 c：其他一样 <br>
<br>
http://news.9duw.com/os/Windows9x/info-6082.html <br>
<br>
另外还有一种安装方法但必须在win7下面安装。 <br>
<br>
<br>
一、windows 7 7000或7022、7048……系统下： <br>
<br>
1、下载windows 7 7057 ISO镜像(RC或RTM)，用虚拟光驱拷贝至非C盘(如D:\7057) <br>
2、开机按F8――修复系统――选择最后一项命令修复――在命令框输入“D:\7057\sources\setup.exe“(不带引号) <br>
3、进入安装界面、选择custom安装 <br>
4、选择安装语言、格式化C盘 <br>
5、OK了，装好后是一个纯系统(非双系统)。 <br>
<br>
二、如果有vista安装盘的话，方法也很简单： <br>
<br>
1、下载windows 7 7057 ISO镜像(RC或RTM)，用虚拟光驱拷贝至非C盘(如D:\7057) <br>
2、BIOS中选择光驱启动，进入vista安装界面 <br>
3、选择左下角修复计算机(自动搜索系统，提示加载驱动或关闭，选择关闭进入修复选项) <br>
4、选择最后一项命令修复，在命令框输入“D:\7057\sources\setup.exe“(不带引号)，开始安装 <br>
5、选择安装语言、格式化C盘 <br>
(即使C盘原本没有系统此法也可行) <br>
<br>
三、XP系统下全新安装windows 7： <br>
<br>
1、下载windows 7 7057 ISO镜像(RC或RTM)，用虚拟光驱拷贝至非C盘(如D:\7057) <br>
2、把D:\7057目录下的bootmgr和boot目录(其实只要里面的boot.sdi和bcd文件)拷贝到c盘根目录下,并在C盘根目录下建个sources文件夹。(XP下不需要取得管理员权限) <br>
3、把D:\7057\sources下的boot.win复制到C盘刚建的sources文件夹 <br>
4、用管理员身份运行cmd，然后输入c:\boot\bootsect.exe /nt60 c: 提示successful(即成功了!) <br>
5、关闭cmd窗口重启计算机，自动进入安装界面，选择安装语言，同时选择适合自己的时间和货币显示种类及键盘和输入方式 <br>
6、出现“开始安装界面”，(要注意了，不点击“现在安装”)点左下角“修复计算机”(repair my computer)，进入&quot;系统恢复选择&quot;，选择最后一项&quot;命令提示符&quot;(command prompt)，进入DOS窗口 <br>
7、输入“D:\7057\sources\setup.exe“(不带引号)，开始安装 <br>
8、选择安装语言、格式化C盘，就OK了 <br>
<br>
四、vista系统下全新安装windows 7(实践证明XP用此种方法也更加方便)： <br>
<br>
1、下载windows 7 7057 ISO镜像(RC或RTM)，用虚拟光驱拷贝至非C盘(如D:\7057) <br>
2、复制D:\7057文件夹中的Boot、EFI、sources文件夹和bootmgr至C盘根目录下 <br>
3、复制D:\7057\boot下Bootsect.exe至C盘根目录下 <br>
第2部需取得管理员权限 <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/87800b5090d1376b853524b2.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%CE%C1%B6%BC%C8%D5">瘟都日</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/87800b5090d1376b853524b2.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-30  11:30</pubDate>
        <category><![CDATA[瘟都日]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/87800b5090d1376b853524b2.html</guid>
</item>

<item>
        <title><![CDATA[8G 优盘制作 linux + winpe 启动盘]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/2f6739ec0e19812e62d09fa9.html]]></link>
        <description><![CDATA[
		
		1. 目标和方法：<br>
为了不分区，为了整个U盘都能被windows识别和使用，采用的方法是：<br>
整个U盘，格式化为fat32，然后在上面放 linux 和 winpe的文件，再在u盘引导分区写入grub，用grub引导linux和winpe。而满足在fat32上跑的linux，简单的就是 puppy拉，它把系统写到一个文件里面去了，这个文件可以放在fat32上。<br>
<br>
2. 制作方法：<br>
(1) winpe<br>
现在的winpe，有老一点的xp的pe，有新一点的支持win7直接安装的pe，老的就是和xp一样的grub引导方式，新的也用chainloader 引导，但是后面跟的文件名不同。<br>
老的，以毛桃版为例，解压后，把里面的minipe文件夹，和ntdetect.com, setupldr.bin, winnt.xpe文件，放到u盘根目录下，并把setupldr.bin重命名为ntldr。这就OK拉，grub里按引导windows方式引导即可。另外，毛桃都也提供自动安装脚本，用那个脚本也好。<br>
新的，如网虫2008等，就不用ntldr引导拉，可以按照它都安装脚本来安装到u盘，但是实际我用了，发现引导阶段提示少了什么东西，然后我就从源目录里找到那些东西，拷贝到u盘中，它提示少文件的地方，就OK了。如果从grub引导，应该是如下代码：<br>
root (hd0,0)<br>
chainloader /minipe/ldrxpe<br>
<br>
(2) linux<br>
我用的puppy，上puppy中国论坛上有汉化的。我现在用的是4.2.1，它也有安装程序叫pup2usb-winpe，但是其实你用grub的话，只用它在u盘根目录解压的puppy文件夹即可，其他的文件，可以删掉。grub中如下书写，其中 in RAM的参数，能够让puppy把文件都调到内存来，并且之后退出linux都时候，你可以决定用不用保存修改过的东西。而下面都那个启动的化，最后它会自动保存修改过的东西，不会问你。<br>
title Puppy Linux in RAM<br>
root&nbsp;&nbsp;  (hd0,0)<br>
kernel /puppy/vmlinuz root=/dev/ram0 PMEDIA=usbflash pfix=ram<br>
initrd /puppy/initrd.gz<br>
<br>
title Puppy Linux 4.2.1<br>
root&nbsp;&nbsp;  (hd0,0)<br>
kernel /puppy/vmlinuz root=/dev/ram0 PMEDIA=usbflash<br>
initrd /puppy/initrd.gz<br>
<br>
(3) grub<br>
grub用grub4dos或者linux下的grub都可以。<br>
用grub4dos的话，要两个东西，一是grub4dos本身，里面含有grldr和menu.lst，这两要拷贝到u盘根目录。二是grubinst_gui，这个能帮助我们把grub写到mbr里。两个做完就OK了。<br>
另外，我用了suse的grub都message，如下：（boot目录拷贝自suse的目录，启动画面不错：）<br>
write 0x7C07 0x00736E6F<br>
gfxmenu (hd0,0)/boot/message<br>
savedefault --wait=2<br>
如果是用linuxgrub的化，把某个linux的boot目录拷贝到u盘根目录，然后进linux，或进已有grub，按照grub安装方法安装即可。只不过，就不需要根目录下的grldr和menu.lst了。<br>
<br>
注意：实践中，对于新的winpe，linux下的grub引导不了，grub4dos可以引导。也可能是我没弄对。<br>
<br> <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/2f6739ec0e19812e62d09fa9.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%CE%C1%B6%BC%C8%D5">瘟都日</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/2f6739ec0e19812e62d09fa9.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-30  11:16</pubDate>
        <category><![CDATA[瘟都日]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/2f6739ec0e19812e62d09fa9.html</guid>
</item>

<item>
        <title><![CDATA[C++ dlopen mini HOWTO 译文]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/f0a30d16fd886458f2de3250.html]]></link>
        <description><![CDATA[
		
		<div align="center"><span style="color: rgb(255, 0, 0);">C++ dlopen mini HOWTO<br>
作者：Aaron Isotton &lt;aaron@isotton.com&gt; 2006-03-16<br>
译者：Lolita@linuxsir.org 2006-08-05</span></div>
------------------------------------------------<br>
<span style="color: rgb(255, 0, 0);">摘要<br>
如何使用dlopen API动态地加载C++函数和类</span><br>
------------------------------------------------<br>
<span style="color: rgb(0, 0, 255);">目录<br>
介绍<br>
版权和许可证<br>
不承诺<br>
贡献者<br>
反馈<br>
术语<br>
问题所在<br>
Name Mangling<br>
类<br>
解决方案<br>
extern &quot;C&quot;<br>
加载函数<br>
加载类<br>
源代码　<br>
FAQ<br>
其他<br>
参考书</span><br>
------------------------------------------------<br>
<span style="color: rgb(0, 0, 255);">介绍</span><br>
如何使用dlopen API动态地加载C++函数和类，是Unix C++程序员经常碰到的问题。事实上，情况偶尔有些复杂，需要一些解释。这正是写这篇mini HOWTO的缘由。<br>
理解这篇文档的前提是对C/C++语言中dlopen API有基本的了解。这篇HOWTO的维护链接是 <a href="http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/" target="_blank">http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/</a> <br>
<br>
<span style="color: rgb(0, 0, 255);">　　版权和许可证</span><br>
这篇文档《C++ dlopen mini HOWTO》版权为Aaron Isotton所有（copyrighted (c) 2002-2006），任何人在遵守自由软件基金会制定的GPLv2许可证条款前提下可以自由拷贝、分发和修改这份文档。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　不承诺</span><br>
本文不对文中的任何内容作可靠性承诺。您必须为您自己使用文中任何概念、示例和信息承担风险，因为其中可能存在错误和不准确的地方，或许会损坏您的系统──尽管几乎不可能发生此类事故，但您还是小心行事──作者不会为此负任何责任。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　贡献者</span><br>
在这篇文档中，我欣然致谢（按字母顺序）：<br>
◆ Joy Y Goodreau &lt;joyg (at) us.ibm.com&gt; 她的编辑工作.<br>
◆ D. Stimitis &lt;stimitis (at) idcomm.com&gt; 指出一些formatting和name mangling的问题, 还指出extern “C”的一些微妙之处。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　反馈</span><br>
欢迎对本文档的反馈信息！请把您的补充、评论和批评发送到这个邮件地址：&lt;aaron@isotton.com&gt;。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　术语</span><br>
dlopen API<br>
关于dlclose、dlerror、dlopen和dlsym函数的描述可以在 dlopen(3) man手册页查到。<br>
请注意，我们使用“dlopen”时，指的是dlopen函数，而使用“dlopen API”则是指整个API集合。<br>
------------------------------------------------<br>
<span style="color: rgb(0, 0, 255);">问题所在</span><br>
有时你想在运行时加载一个库（并使用其中的函数），这在你为你的程序写一些插件或模块架构的时候经常发生。<br>
在C语言中，加载一个库轻而易举（调用dlopen、dlsym和dlclose就够了），但对C++来说，情况稍微复杂。动态加载一个C++库的困难 一部分是因为C++的name mangling（译者注：也有人把它翻译为“名字毁坏”，我觉得还是不翻译好），另一部分是因为dlopen API是用C语言实现的，因而没有提供一个合适的方式来装载类。<br>
在解释如何装载C++库之前，最好再详细了解一下name mangling。我推荐您了解一下它，即使您对它不感兴趣。因为这有助于您理解问题是如何产生的，如何才能解决它们。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　Name Mangling</span><br>
在每个C++程序（或库、目标文件）中，所有非静态（non-static）函数在二进制文件中都是以“符号（symbol）”形式出现的。这些符号都是唯一的字符串，从而把各个函数在程序、库、目标文件中区分开来。<br>
在C中，符号名正是函数名：strcpy函数的符号名就是“strcpy”，等等。这可能是因为两个非静态函数的名字一定各不相同的缘故。<br>
而C++允许重载（不同的函数有相同的名字但不同的参数），并且有很多C所没有的特性──比如类、成员函数、异常说明──几乎不可能直接用函数名作符号 名。为了解决这个问题，C++采用了所谓的name mangling。它把函数名和一些信息（如参数数量和大小）杂糅在一起，改造成奇形怪状，只有编译器才懂的符号名。例如，被mangle后的foo可能 看起来像foo@4%6^，或者，符号名里头甚至不包括“foo”。<br>
其中一个问题是，C++标准（目前是[ISO14882]）并没有定义名 字必须如何被mangle，所以每个编译器都按自己的方式来进行name mangling。有些编译器甚至在不同版本间更换mangling算法（尤其是g++ 2.x和3.x）。即使您搞清楚了您的编译器到底怎么进行mangling的，从而可以用dlsym调用函数了，但可能仅仅限于您手头的这个编译器而已， 而无法在下一版编译器下工作。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　类</span><br>
使用dlopen API的另一个问题是，它只支持加载函数。但在C++中，您可能要用到库中的一个类，而这需要创建该类的一个实例，这不容易做到。<br>
<br>
<span style="color: rgb(0, 0, 255);">解决方案</span><br>
<br>
<span style="color: rgb(0, 0, 255);">extern &quot;C&quot;</span><br>
C++有个特定的关键字用来声明采用C binding的函数：extern &quot;C&quot; 。 用 extern &quot;C&quot;声明的函数将使用函数名作符号名，就像C函数一样。因此，只有非成员函数才能被声明为extern &quot;C&quot;，并且不能被重载。尽管限制多多，extern &quot;C&quot;函数还是非常有用，因为它们可以象C函数一样被dlopen动态加载。冠以extern &quot;C&quot;限定符后，并不意味着函数中无法使用C++代码了，相反，它仍然是一个完全的C++函数，可以使用任何C++特性和各种类型的参数。<br>
<br>
<span style="color: rgb(0, 0, 255);">加载函数</span><br>
在C++中，函数用dlsym加载，就像C中一样。不过，该函数要用extern &quot;C&quot;限定符声明以防止其符号名被mangle。<br>
<br>
示例1.加载函数<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">//----------<br>
//main.cpp:<br>
//----------<br>
#include &lt;iostream&gt;<br>
#include &lt;dlfcn.h&gt;<br>
<br>
int main() {<br>
using std::cout;<br>
using std::cerr;<br>
<br>
cout &lt;&lt; &quot;C++ dlopen demo\n\n&quot;;<br>
<br>
// open the library<br>
cout &lt;&lt; &quot;Opening hello.so...\n&quot;;<br>
void* handle = dlopen(&quot;./hello.so&quot;, RTLD_LAZY);<br>
<br>
if (!handle) {<br>
cerr &lt;&lt; &quot;Cannot open library: &quot; &lt;&lt; dlerror() &lt;&lt; '\n';<br>
return 1;<br>
}<br>
<br>
// load the symbol<br>
cout &lt;&lt; &quot;Loading symbol hello...\n&quot;;<br>
typedef void (*hello_t)();<br>
<br>
// reset errors<br>
dlerror();<br>
hello_t hello = (hello_t) dlsym(handle, &quot;hello&quot;);<br>
const char *dlsym_error = dlerror();<br>
if (dlsym_error) {<br>
cerr &lt;&lt; &quot;Cannot load symbol 'hello': &quot; &lt;&lt; dlsym_error &lt;&lt;<br>
'\n';<br>
dlclose(handle);<br>
return 1;<br>
}<br>
<br>
// use it to do the calculation<br>
cout &lt;&lt; &quot;Calling hello...\n&quot;;<br>
hello();<br>
<br>
// close the library<br>
cout &lt;&lt; &quot;Closing library...\n&quot;;<br>
dlclose(handle);<br>
}<br>
<br>
//----------<br>
// hello.cpp:<br>
//----------<br>
#include &lt;iostream&gt;<br>
<br>
extern &quot;C&quot; void hello() {<br>
std::cout &lt;&lt; &quot;hello&quot; &lt;&lt; '\n';<br>
}</code>  <hr>
</div>
在hello.cpp中函数hello被定义为extern &quot;C&quot;。它在main.cpp中被dlsym调用。函数必须以extern &quot;C&quot;限定，否则我们无从知晓其符号名。<br>
警告：<br>
extern &quot;C&quot;的声明形式有两种：上面示例中使用的那种内联（inline）形式extern &quot;C&quot; ， 还有才用花括号的extern &quot;C&quot; { ... }这种。 第一种内联形式声明包含两层意义：外部链接(extern linkage)和C语言链接(language linkage)，而第二种仅影响语言链接。<br>
下面两种声明形式等价：<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">extern &quot;C&quot; int foo;<br>
extern &quot;C&quot; void bar();</code>  <hr>
</div>
和<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">extern &quot;C&quot; {<br>
extern int foo;<br>
extern void bar();<br>
}</code>  <hr>
</div>
对于函数来说，extern和non-extern的函数声明没有区别，但对于变量就有不同了。如果您声明变量，请牢记：<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">extern &quot;C&quot; int foo;</code>  <hr>
</div>
和<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">extern &quot;C&quot; {<br>
int foo;<br>
}</code>  <hr>
</div>
是不同的物事(译者注：简言之，前者是个声明; 而后者不仅是声明，也可以是定义)。<br>
进一步的解释请参考[ISO14882],7.5, 特别注意第7段; 或者参考[STR2000]，9.2.4。在用extern的变量寻幽访胜之前，请细读“其他”一节中罗列的文档。<br>
<br>
<span style="color: rgb(0, 0, 255);">　　加载类</span><br>
加载类有点困难，因为我们需要类的一个实例，而不仅仅是一个函数指针。我们无法通过new来创建类的实例，因为类不是在可执行文件中定义的，况且（有时候）我们连它的名字都不知道。<br>
解决方案是：利用多态性！ 我们在可执行文件中定义一个带虚成员函数的接口基类，而在模块中定义派生实现类。通常来说，接口类是抽象的（如果一个类含有虚函数，那它就是抽象的）。<br>
因为动态加载类往往用于实现插件，这意味着必须提供一个清晰定义的接口──我们将定义一个接口类和派生实现类。<br>
接下来，在模块中，我们会定义两个附加的helper函数，就是众所周知的“类工厂函数（class factory functions）（译者注：或称对象工厂函数）”。其中一个函数创建一个类实例，并返回其指针; 另一个函数则用以销毁该指针。这两个函数都以extern &quot;C&quot;来限定修饰。<br>
为了使用模块中的类，我们用dlsym像示例1中加载hello函数那样加载这两个函数，然后我们就可以随心所欲地创建和销毁实例了。<br>
<br>
示例2.加载类<br>
我们用一个一般性的多边形类作为接口，而继承它的三角形类（译者注：正三角形类）作为实现。<br>
<div style="margin: 5px 20px 20px;">
<div class="smallfont" style="margin-bottom: 2px;">代码:</div>
<hr>
<code dir="ltr" style="margin: 0px; text-align: left;">//----------<br>
//main.cpp:<br>
//----------<br>
#include &quot;polygon.hpp&quot;<br>
#include &lt;iostream&gt;<br>
#include &lt;dlfcn.h&gt;<br>
<br>
int main() {<br>
using std::cout;<br>
using std::cerr;<br>
<br>
// load the triangle library<br>
void* triangle = dlopen(&quot;./triangle.so&quot;, RTLD_LAZY);<br>
if (!triangle) {<br>
cerr &lt;&lt; &quot;Cannot load library: &quot; &lt;&lt; dlerror() &lt;&lt; '\n';<br>
return 1;<br>
}<br>
<br>
// reset errors<br>
dlerror();<br>
<br>
// load the symbols<br>
create_t* create_triangle = (create_t*) dlsym(triangle, &quot;create&quot;);<br>
const char* dlsym_error = dlerror();<br>
if (dlsym_error) {<br>
cerr &lt;&lt; &quot;Cannot load symbol create: &quot; &lt;&lt; dlsym_error &lt;&lt; '\n';<br>
return 1;<br>
}<br>
<br>
destroy_t* destroy_triangle = (destroy_t*) dlsym(triangle, &quot;destroy&quot;);<br>
dlsym_error = dlerror();<br>
if (dlsym_error) {<br>
cerr &lt;&lt; &quot;Cannot load symbol destroy: &quot; &lt;&lt; dlsym_error &lt;&lt; '\n';<br>
return 1;<br>
}<br>
<br>
// create an instance of the class<br>
polygon* poly = create_triangle();<br>
<br>
// use the class<br>
poly-&gt;set_side_length(7);<br>
cout &lt;&lt; &quot;The area is: &quot; &lt;&lt; poly-&gt;area() &lt;&lt; '\n';<br>
<br>
// destroy the class<br>
destroy_triangle(poly);<br>
<br>
// unload the triangle library<br>
dlclose(triangle);<br>
}<br>
<br>
<br>
//----------<br>
//polygon.hpp:<br>
//----------<br>
#ifndef POLYGON_HPP<br>
#define POLYGON_HPP<br>
<br>
class polygon {<br>
protected:<br>
double side_length_;<br>
<br>
public:<br>
polygon()<br>
: side_length_(0) {}<br>
<br>
virtual ~polygon() {}<br>
<br>
void set_side_length(double side_length) {<br>
side_length_ = side_length;<br>
}<br>
<br>
virtual double area() const = 0;<br>
};<br>
<br>
// the types of the class factories<br>
typedef polygon* create_t();<br>
typedef void destroy_t(polygon*);<br>
<br>
#endif<br>
<br>
//----------<br>
//triangle.cpp:<br>
//----------<br>
#include &quot;polygon.hpp&quot;<br>
#include &lt;cmath&gt;<br>
<br>
class triangle : public polygon {<br>
public:<br>
virtual double area() const {<br>
return side_length_ * side_length_ * sqrt(3) / 2;<br>
}<br>
};<br>
<br>
<br>
// the class factories<br>
extern &quot;C&quot; polygon* create() {<br>
return new triangle;<br>
}<br>
<br>
extern &quot;C&quot; void destroy(polygon* p) {<br>
delete p;<br>
}</code>  <hr>
</div>
加载类时有一些值得注意的地方：<br>
◆ 你必须（译者注：在模块或者说共享库中）同时提供一个创造函数和一个销毁函数，且不能在执行文件内部使用delete来销毁实例，只能把实例指针传递给模 块的销毁函数处理。这是因为C++里头，new操作符可以被重载;这容易导致new-delete的不匹配调用，造成莫名其妙的内存泄漏和段错误。这在用 不同的标准库链接模块和可执行文件时也一样。<br>
◆ 接口类的析构函数在任何情况下都必须是虚函数（virtual）。因为即使出错的可能极小，近乎杞人忧天了，但仍旧不值得去冒险，反正额外的开销微不足 道。如果基类不需要析构函数，定义一个空的（但必须虚的）析构函数吧，否则你迟早要遇到问题，我向您保证。你可以在comp.lang.c++ FAQ( <a href="http://www.parashift.com/c++-faq-lite/" target="_blank">http://www.parashift.com/c++-faq-lite/</a> )的第20节了解到更多关于该问题的信息。<br>
<br>
<span style="color: rgb(0, 0, 255);">源代码</span><br>
你可以下载所有包含在本文档中的代码包： <a href="http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/examples.tar.gz" target="_blank">http://www.isotton.com/howtos/C++-dl...xamples.tar.gz</a><br>
<br>
<span style="color: rgb(0, 0, 255);">FAQ</span><br>
(译者注：下文翻译暂时省略)<br>
1.I'm using Windows and I can't find the dlfcn.h header file! What's the problem?<br>
<br>
The problem is that Windows doesn't have the dlopen API, and thus there is no dlfcn.h header. There is a similar API around the LoadLibrary function, and most of what is written here applies to it, too. Please refer to the Microsoft Developer Network Website for more information.<br>
<br>
2.Is there some kind of dlopen-compatible wrapper for the Windows LoadLibrary API?<br>
<br>
I don't know of any, and I don't think there'll ever be one supporting all of dlopen's options.<br>
<br>
There are alternatives though: libtltdl (a part of libtool), which wraps a variety of different dynamic loading APIs, among others dlopen and LoadLibrary. Another one is the Dynamic Module Loading functionality of GLib. You can use one of these to ensure better possible cross-platform compatibility. I've never used any of them, so I can't tell you how stable they are and whether they really work.<br>
<br>
You should also read section 4, “Dynamically Loaded (DL) Libraries”, of the Program Library HOWTO for more techniques to load libraries and create classes independently of your platform.<br>
<br>
<br>
<span style="color: rgb(0, 0, 255);">其他</span><br>
<br>
* The dlopen(3) man page. It explains the purpose and the use of the dlopen API.<br>
* The article Dynamic Class Loading for C++ on Linux by James Norton published on the Linux Journal.<br>
* Your favorite C++ reference about extern &quot;C&quot;, inheritance, virtual functions, new and delete. I recommend [STR2000].<br>
* [ISO14882]<br>
* The Program Library HOWTO, which tells you most things you'll ever need about static, shared and dynamically loaded libraries and how to create them. Highly recommended.<br>
* The Linux GCC HOWTO to learn more about how to create libraries with GCC.<br>
<br>
<span style="color: rgb(0, 0, 255);">参考书目</span><br>
[ISO14482] ISO/IEC 14482-1998 — The C++ Programming Language. Available as PDF and as printed book from <a href="http://webstore.ansi.org/" target="_blank">http://webstore.ansi.org/</a>.<br>
[STR2000] StroustrupBjarne The C++ Programming Language, Special Edition. ISBN 0-201-70073-5. Addison-Wesley <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/f0a30d16fd886458f2de3250.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/f0a30d16fd886458f2de3250.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-22  16:47</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/f0a30d16fd886458f2de3250.html</guid>
</item>

<item>
        <title><![CDATA[Learning Perl 5th edition (perl 5.10) - part 2]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/5c686703393f62e509fa9317.html]]></link>
        <description><![CDATA[
		
		<p>Note:</p>
<p>Chapter 1. Introduction</p>
<p>Unix: #!/usr/bin/perl -w  or&nbsp;&nbsp;  #!/usr/bin/env perl (use -w because we like warnings)<br>
windows: #!perl</p>
<p><br>
Chapter 2. Scalar Data<br>
Scalar data: undef, double(integer is actually doubles), string<br>
List&nbsp;&nbsp;  data: list of scalar element. refer to Chapter 3.</p>
<p>undef  data: it's another kind of scalar data. if you use a var without definition, it contains undef value, not string or doubles<br>
eg.<br>
$blank = $fred[142_857]; will try to get the 142_857th var which is not defined and an undef data tyep value is returned to $blank<br>
undef value are widely used to represent &quot;no ordinary value to return&quot;. eg. &lt;STDIN&gt; return undef if reaching the EOF. so we'll omit many such cases in the following note.<br>
we can use defined(xxx) function to return true for defined value and false for undef value in condition test.</p>
<p>double begins with:<br>
0(Octal base8)<br>
0x(Hex base16)<br>
0b(Bin base2)</p>
<p>string's char can be like:<br>
\0.. char in octal<br>
\x.. char in hex</p>
<p>string should be used with '' or &quot;&quot;<br>
'': only \ can be used to escape sth.<br>
&quot;&quot;: \, $ and @ can be used. (@ is used to lead array, but unfortunately % is not allowed to lead hashes)</p>
<p>special operator:<br>
&quot;hello&quot;.&quot;world&quot; = &quot;helloworld&quot;<br>
&quot;fred&quot;x3 = &quot;fredfredfred&quot;<br>
5x4 = &quot;5555&quot;</p>
<p>how to use warnings:<br>
(1) -w added to the perl command<br>
(2) use warnings;<br>
how to use diagnostics(warings with long message):<br>
(1) use diagnostics;<br>
(2) -Mdiagnostics added to the perl command</p>
<p>always use $ ahead of a variable !! (don't confuse it with shell var usage)</p>
<p>print:<br>
(1) use , to seperate params:<br>
print &quot;the answer is&quot;, 6*7, &quot;.\n&quot;;<br>
(2) use ${} to keep clear:<br>
print &quot;fred ate ${what}s.\n&quot;&nbsp;&nbsp;  or you can<br>
print &quot;fred ate $what&quot;.&quot;s.\n&quot;</p>
<p>unlike shell, single var need not &quot;&quot; to avoid empty string error</p>
<p>comparasion operator is opposite to shell:<br>
doubles: == != &lt; &gt; &lt;= &gt;=<br>
strings: eq ne lt gt le ge</p>
<p>boolean:<br>
double: 0 false  others true<br>
string: '' false others true<br>
others: convert them to double or string first</p>
<p>input:<br>
just  $line=&lt;STDIN&gt;;  then you get the line including the '\n' in $line</p>
<p>chomp:<br>
remove the last '\n' of a string<br>
it's very useful because it's simplicity. and it's often used after $line=&lt;STDIN&gt; to <br>
get rid of the last '\n'</p>
<p> </p>
<p><br>
Chapter 3 Lists and Arrays<br>
List are list of scalar values(right value), Array is simply an variable to hold the list(left value)<br>
ie. List are just collection of variables to represent collection of values. we can use ($fred, $barney) to represent the two variables as a whole. so you can do some operations on them as a whole. eg. assignment to them can be done like this: ($fred, $barney)=(1,2); so essentially list has nothing to do with array. But array use list internally to hold data.<br>
And any place where scalar value is used, list can be used!!</p>
<p>we can use list to exchange two vars:<br>
($fred, $barney)=($barney, $fred);</p>
<p>to use array, you don't need to define it, just use it! it will extend itself on need.<br>
do it like this: (we use $ to refer an element, @ to refer the whole array)<br>
$rocks[0]='haha';<br>
$rocks[99]='schist';  (the var $#rocks indicate the last element index, ie. 99)<br>
@rocks=(1,2,3,4,5,6);<br>
@rocks=(1..10);<br>
@rocks=(&quot;bedrock&quot;, &quot;slate&quot;, &quot;lava&quot;);  equals @rocks=qw(bedrock slate lava);<br>
(qw can help us to avoid the &quot;&quot;, it can use () !! ## // etc... to enclose values)<br>
@home=(@rocks, &quot;mother&quot;, &quot;father&quot;);</p>
<p>pop, push, shift, unshift -- the faster way to resize the array.(compared with index)<br>
We use them if possible instead of index !!!!!<br>
@array=(1..10);<br>
@m = pop @array;&nbsp;&nbsp;  #(1..9)<br>
push @array,10;&nbsp;&nbsp;&nbsp;  #(1..10)<br>
@n = shift @array; #(2..10)<br>
unshift @array,1;  #(1..10)</p>
<p>use foreach to iterate list(array) like this:<br>
we iterate list, so () is needed after the $loopvar.<br>
foreach $loopvar (@array) {<br>
 # do sth<br>
}<br>
foreach $loopvar (&quot;bed&quot;, &quot;room&quot;, &quot;chair&quot;)) {<br>
 # do sth<br>
}<br>
foreach $loopvar (qw(bed room chair)) {<br>
 # do sth<br>
}<br>
but we always omit $loopvar, because the system defined $_ will play the role. and functions like print will by default use $_ if you just type print;<br>
foreach (@array) {<br>
 print &quot;$_&quot;;<br>
}</p>
<p>reverse and sort:  -- if you don't assigned it to left value, nothing happened !!<br>
we can use them to do operation on a list/array:<br>
@fred = reverse @fred;<br>
@fred = sort @fred;</p>
<p>the most important section of this book: -- you must get used to it!!!<br>
expression(like variable, function)'s value is dependent on what is expected, ie: scalar value or list value.<br>
it may sound strange to C programmers because the function's return value is also dependent on what is expected. eg:<br>
@list = @people # a list<br>
$n = @people&nbsp;&nbsp;&nbsp;  # people list's elements count is assigned to $n !! very useful !!!<br>
@backwards=reverse qw(yabba dabba doo);  # a list is reversed and asigned<br>
$backwards=reverse qw(yabba dabba doo);  # a list is reversed and catenated to a string which is assigned to backwards.</p>
<p>&lt;STDIN&gt; can be used in list value context:<br>
@lines = &lt;STDIN&gt;; # every line will be treated as an element and EOF will end the reading. CTL+D on Unix or CTL+Z on Windows leads to EOF. <br>
chomp(@lines=&lt;STDIN&gt;); can also be used.</p>
<p><br>
Chapter 4 Subroutines<br>
-------- below is a perl script of quick reference to usage of subroutines ---------<br>
#!perl<br>
use strict; <br>
# we always use strict to be strict to our potential errors.<br>
# if use strict is used, global var is not allowed !!! always use my() before your vars</p>
<p>sub saysth {  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <br>
 # my must be used if local var are to be defined. and () must be used if more than one vars.<br>
 # @_ is the predefined var for params list whose index starts from index 0.<br>
 # this line is very common to assign params to meaningful names, and use them later instead of @_.<br>
 # and $_[] is used to access @_'s elements if you want to use @_ directly.<br>
 # NOTICE: the $_[] has nothing to do with the $_(which is widely used, eg. the loop var of foreach)<br>
 my ($father, $son) = @_; <br>
 print $father, $_[0];  # the two var are the same<br>
 print $son, $_[1];&nbsp;&nbsp;&nbsp;&nbsp;  # the two var are the same</p>
<p> # this is the scalar context, so we assign @_'s elements count to arg_count<br>
 my $arg_count = @_;&nbsp;&nbsp;&nbsp;  # always use my to define local variables ! we seldom need global ones.<br>
 print &quot;$arg_count\n&quot;;</p>
<p> # use wantarray fun to test where we return to scalar or list context.<br>
 # but if no proper value can be returned , we simply use &quot;return&quot; to automatically<br>
 # return undef in scalar context and null list in list context<br>
 if (wantarray) {<br>
&nbsp;&nbsp; (1..10);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we always omit return if this is the last sentence to execute.<br>
 }else {<br>
&nbsp;&nbsp; return 5;&nbsp;&nbsp;&nbsp;&nbsp;  # strict programmers like to use return.<br>
 }<br>
}</p>
<p>my @cows = &amp;saysth;<br>
my $sheep = &amp;saysth;</p>
<p>print &quot;@cows\n&quot;;<br>
print &quot;$sheep\n&quot;;</p>
<p>-------- endof perl script --------</p>
<p>NOTE:  about ()<br>
sth you must know: fun(a, b, c); is the same as what we see in C language. but we often omit (), ie. fun a, b, c;</p>
<p><br>
Chapter 5 Input and Output<br>
1. how to input<br>
we use:<br>
while (&lt;STDIN&gt;) {<br>
 chomp($_);<br>
 print &quot;I saw $_&quot;;<br>
}<br>
instead of <br>
while (defined(my $line=&lt;STDIN&gt;)) {<br>
 chomp($line);<br>
 print &quot;I saw $line&quot;;<br>
}<br>
because it's complicated,<br>
instead of <br>
foreach (&lt;STDIN&gt;) {<br>
 print &quot;I saw $_&quot;;<br>
}<br>
because foreach requires a list value, which cause &lt;STDIN&gt; to hold the whole input until EOF is encountered,<br>
and then enter the foreach loop which will cause bad performance in reading large files !!!</p>
<p>NOTE: &lt;STDIN&gt; may return a scalar of a list too.</p>
<p>2. how to act like unix tool behavior: <br>
(1) file arg can be replaced with -<br>
(2) perl script can be used in pipe condition<br>
eg. &quot;cat file1.txt file2.txt&quot; can be replaced with &quot;cat -&quot; (or just cat) if you prefer STDIN<br>
we use:<br>
while (&lt;&gt;) {<br>
 chomp;<br>
 print &quot;It was $_ that I saw!\n&quot;;<br>
}<br>
instead of<br>
while (define(my $line = &lt;&gt;)) {<br>
 chomp($line);<br>
 print &quot;It was $line that I saw!\n&quot;<br>
}<br>
because it's complicated,<br>
NOTE: &lt;&gt; may return a scalar of a list too.</p>
<p>3. @ARGV<br>
the cmd line args array which we can use &quot;shift&quot; or &quot;foreach&quot; to iterate<br>
eg.<br>
my $arg1 = shift @ARGV;</p>
<p>4. output the array:<br>
my @array=qw(sheep cow chick);<br>
print @array;  # sheepcowchick<br>
print &quot;@array&quot; # sheep cow chick</p>
<p>5. cat and sort<br>
print &lt;&gt;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # &lt;&gt; return a list. and print display it.<br>
print sort &lt;&gt;;&nbsp;&nbsp;  # the unix sort function</p>
<p>6. weird print:<br>
print (2+3)*4;  # only 5 is printed. because if there's () behind print, print will be used as a function. it will only print the result in () and return , saying 1.<br>
so do it like this: <br>
print ((2+3)*4);</p>
<p>NOTE: if () is given, print only print the result in (). if not given, print will print all the stuff following itself, ie. treat them all as a list value.</p>
<p>7. printf:<br>
the same as C printf.<br>
eg.<br>
printf (&quot;%12.3f\n&quot;, 6*7+2/3); # width is 12, right alignment, allow 3 digit after the dot of float</p>
<p>except:<br>
(1)%g is provided to automatically select float, int or exp<br>
(2)%% can be used to print &quot;%&quot;. not \% !!!!! \% won't work :(<br>
(3)print array:<br>
printf &quot;The items are:\n&quot;.(&quot;%10s\n&quot; x @items), @items; <br>
# the first @items is in the scalar context and return the size of the array. <br>
# the second @items is in the list context and return the list of the array.</p>
<p>8. the filehandle<br>
6 predefined: STDIN, STDOUT, STDERR, DATA, ARGV, ARGVOUT<br>
(1) open file for read,write,append:<br>
open CONFIG, &quot;&lt;dino.txt&quot;;&nbsp;&nbsp;&nbsp;  # open dino.txt for read, CONFIG is the filehandler<br>
open BEDROCK, &quot;&gt;fred.txt&quot;;&nbsp;&nbsp;  # open fred.txt for write, BEDROCK is the filehandler<br>
open LOG, &quot;&gt;&gt;logfile.txt&quot;;&nbsp;&nbsp;  # open logfile.txt for appending, LOG is the filehandler<br>
(2) close file:<br>
just &quot;close filehandle;&quot;<br>
(3) check open error:<br>
if (!open LOG, &quot;&gt;&gt;logfile.txt&quot;) {<br>
 die &quot;open logfile.txt error: $!&quot;;  <br>
&nbsp;&nbsp;&nbsp;  # we use $! to get what perror give us, ie. system error info<br>
 # if we dont use the linux system API, omit the $! here.<br>
}<br>
or you can use a var to hold the return value:<br>
my $success = open LOG, &quot;&gt;&gt;logfile.txt&quot;;<br>
if (!$success) {<br>
 die &quot;...&quot;;<br>
}<br>
or we can just use &quot;warn&quot; to warn users without exit.<br>
(4) read from/write to filehandler (predefined or user-defined filehandler)<br>
read:<br>
if (!open PASSWD, &quot;/etc/passwd&quot;) {<br>
 die &quot;how did you get logged in?($!)&quot;;<br>
}<br>
while(&lt;PASSWD&gt;){<br>
 chomp;<br>
 #...<br>
}<br>
write: use print or printf<br>
print LOG &quot;Captain's log, stardate 3.14159\n&quot;;<br>
printf LOG &quot;%d percent complete.\n&quot;, $done/$total *100;<br>
or look more like c:<br>
printf (LOG &quot;%d percent complete.\n&quot;, $done/$total *100);<br>
(5) how to make the default output to other filehandle other than STDOUT ?<br>
select PASSWD; # select can be only used to choose which filehandler to output<br>
# do sth dirty<br>
select STDOUT; # set it back<br>
(6) how to direct STDERR etc. to files instead of let user use &gt; in command line ?<br>
just reopen them:<br>
if (!open stderr, &quot;&gt;&gt;/home/barney/.error_log&quot;) {<br>
 die &quot;Can't open error log for append:$!&quot;<br>
}<br>
now, every stderr message will be sent to .error_log</p>
<p><br>
Chapter 6 Hashes<br>
example makes every clear:<br>
--------<br>
#!perl<br>
use strict;</p>
<p>my %stupid_hash = (&quot;she&quot;,20,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we can create a hash table like this<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &quot;me&quot;, 21);<br>
my %silly_hash = (&quot;she&quot;=&gt;20, &quot;me&quot;=&gt;21);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we can also create a hash table like this using =&gt; instead of ,<br>
$silly_hash{&quot;we&quot;} = &quot;41&quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we can create a new &quot;key-value&quot; pair like this</p>
<p>print %silly_hash,&quot;\n&quot;;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # result is &quot;she20we41me21&quot;, in which we can see that the sequence <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # is based on the actual storing structure not the input sequence<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # and % is not special in &quot; &quot; !<br>
my @hash_array = %silly_hash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we can also do assignment from hash to list(array).<br>
print &quot;@hash_array\n&quot;;</p>
<p><br>
my %clever_hash = reverse %silly_hash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # now values become the keys !<br>
my @keys = keys %silly_hash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # only get the keys list<br>
my @values = values %silly_hash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # only get the values list<br>
my $count = keys %silly_hash;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # here the keys are in scalar context which return the count of keys<br>
print %clever_hash, &quot;\n@keys\n@values\n$count\n&quot;;</p>
<p># method 1 for iteration:<br>
# the each function will return a list contains only the current pair. when there's no more pairs,<br>
# the each will return empty list to ($key, $value) which will cause $key and $value to be undef.<br>
# but the key points here is: the empty list in while() scalar context will return 0 to indicate<br>
# the element is has. so the while will quit. (in condition, like C, 0 indicates false)<br>
while((my $key, my $value) = each %silly_hash) {&nbsp;&nbsp;&nbsp;&nbsp;  # each is only used in while in actual use.<br>
 print &quot;$key =&gt; $value\n&quot;;<br>
}</p>
<p># method 2 for iteration:<br>
# if you want to sort what the %silly_hash returns, use sort which return a list.<br>
# then use foreach to iterate the list.<br>
foreach my $key (sort keys %silly_hash) {<br>
 my $value = $silly_hash{$key};<br>
 print &quot;$key=&gt;$value\n&quot;;<br>
}</p>
<p># use exists to test where a key exists.<br>
if (exists $silly_hash{&quot;she&quot;}) {<br>
 print &quot;she exists!\n&quot;;<br>
}</p>
<p># delete a key=&gt;value pair<br>
delete $silly_hash{&quot;she&quot;};<br>
print %silly_hash;<br>
---------</p>
<p><br>
Chapter 7 In the World of Regular Expressions<br>
compared with Chapter 8&amp;9, this chapter tell us the general RE patterns.<br>
special points: (in addition to common sense)<br>
(1) /./ dosen't match the new line char<br>
(2) how to match any string including null string:<br>
/(fred)*/ matches any string including null string.(because * can match 0 fred, which means every string)<br>
(3) /fred (and|or) barney/  matches fred and barney, fred or barney. <br>
(4) abbr.:  [0-9] =&gt; \d&nbsp;&nbsp;&nbsp;  [A-Za-z0-9_] =&gt; \w&nbsp;&nbsp;&nbsp;  [\f\t\n\r ] =&gt; \s<br>
so we often see  \w+  \s+  etc ...<br>
(5) abbr2:  [^\d] =&gt; \D&nbsp;&nbsp;&nbsp;  [^\w] =&gt; \W&nbsp;&nbsp;&nbsp;&nbsp;  [^\s] =&gt; \S<br>
(6) [\000-\177]+  matches every 7 bits ASCII char string<br>
[\dA-Fa-f]+ matches any hex numbers<br>
(7) how to match any char including new line char:  <br>
[\d\D]  which means any digit and any non digit, ie. any chars<br>
(8) to bound sth:<br>
bound is the &quot;visual char&quot; which dosen't really exist in string.<br>
^  head<br>
$  tail(including \n)<br>
\b bound of a word(\w)  (every word has two bounds. actually \&lt; \&gt; is more common in general RE)<br>
eg. <br>
/\bhunt/ matches hunt, hunting, not anthunt.<br>
/\bhunt\b/ matches hunt, not any other words.<br>
\B is the opposite of \b which means not a bound.<br>
(9) how many times:<br>
eg.<br>
/(fred){5,15}/<br>
/(fred){5,}/&nbsp;&nbsp;&nbsp;  # equal or more than 5 times<br>
/\w{9}/<br>
(10) backreferences:<br>
NOTICE: \n refer to the n th () before it. here we add {2} after \1 to match the &quot;theretherethere&quot;<br>
eg.<br>
$_=&quot;Hello theretherethere, neighbor&quot;;<br>
if (/(t\w{4})\1{2}/) {<br>
 print &quot;words were $1&quot;;<br>
}</p>
<p> </p>
<p><br>
Chapter 8 &amp; 9  Matching &amp; Processing with Regular Expressions<br>
this chapter tell us the especial perl style expression to use RE to process text.<br>
these symbols are only for use in perl, like /i to ignore case.<br>
1. m//<br>
you can use m{} m&lt;&gt; ... but we often use m//. actually, // is the abbr of m//.<br>
the m// return true of false, so we can use it directly in condition test.<br>
NOTICE: if we choose // to enclose the RE, we must use \ to escape / in RE if we wanna match /.<br>
(1) basic usage:<br>
$_=&quot;Hello kitty!&quot;;<br>
if (/kitty/) {<br>
 print &quot;found!\n&quot;;<br>
}<br>
(2) useful flags:<br>
/i: ignore case<br>
if (/Kitty/i) {<br>
 print &quot;found!\n&quot;;<br>
}<br>
/s: to let . to include \n<br>
if (/Barney.*Fred/s) {<br>
 print &quot;found!\n&quot;<br>
}<br>
/x: to let you use space and comment<br>
you may wanna know this topic if you wanna you RE more readable.<br>
(3) &quot;matching variable&quot;: <br>
() in perl has special usage except grouping REs. we can use $1 ~ $n to refer to them after matching completes, which is very powerful.<br>
NOTICE: VERY IMPORTANT!!! use it only when you know that the matching will succeed, otherwise the &quot;matching variables&quot; will remain the value as that of last time successful matching.<br>
eg.<br>
$_=&quot;Hello there, neighbor&quot;;<br>
if (/(\S+) (\S+), (\S+)/) {<br>
 print &quot;words were $1 $2 $3\n&quot;;<br>
}<br>
(4) slow &quot;matching variable&quot;:<br>
these 3 vars cause other perl RE processing slow. but if convenience is what you want,use them.<br>
int the following case, $&amp; is the matching part, $` is anything before that, $' is anything after that. so if you put these 3 vars together, you get the whole string.<br>
eg.<br>
if (&quot;Hello there, neighbor&quot; =~ /\S(\w+),/) {<br>
 print &quot;That was ($`)($&amp;)($')&quot;;  <br>
}<br>
(5) the &quot;binding operator&quot; =~ can help us to use self-defined var instead of $_:<br>
NOTICE: =~ return true of false which can be used in conditon testing.<br>
eg. <br>
my $str = &quot;I dream of betty rubble.&quot;;<br>
if ($str =~ /\brub/) {<br>
 print &quot;Aye, there's the rub.\n&quot;;<br>
}</p>
<p>2. s/A/B/<br>
return a bool value. true for successfully replace. false for failure.<br>
NOTICE: A is a Regular Pattern, and B is a normal string(so don't need escape char like \ in B)<br>
(1) basic:<br>
---- use $_ -----<br>
$_ = &quot;cow is not sheep!&quot;;<br>
s/cow/dog/;<br>
print &quot;$_\n&quot;;<br>
---- use local var ----<br>
my $filename =~ s/cow/dog/; # the =~ here also returns true for matching, false for no matching<br>
print &quot;$filename\n&quot;<br>
(2) common replace and insertion:<br>
$_=&quot;green scaly dinosaur&quot;;<br>
s/(\w+) (\w+)/$2,$1/;  # replace eg. result &quot;scaly, green dinosaur&quot;<br>
s/^/huge, /;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # insert at the beginning. result &quot;huge, scaly, green dinosaur&quot; <br>
s/$/ child/;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # insert at the end. result &quot;huge, scaly, green dinosaur child&quot; <br>
s/\w+$/($`!)$&amp;/;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # example of using $` and $&amp; (possibly $' to do insertion)<br>
s/\s+/ /g;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # use g to do global replacement. here we shrink spaces.<br>
(3) case swith:<br>
$_=&quot;I saw Barney with Fred.&quot;;<br>
s/(fred|barney)/\U$1\E/gi;  # result &quot;I saw BARNEY with FRED.&quot;; <br>
# here we use \U to make $1 in upper case. use \E to indicate the end of conversion.<br>
we can also use \L to make them in lower case. use \u to make only the first char in upper case and \l to make the first char in lower case.<br>
(4) use bake file:<br>
$^I=&quot;.bak&quot;; # if we set $^I, s/// will do real change, and bake the old file as *.bak<br>
while(&lt;&gt;) {<br>
 s/^Author:.*/Author: Randal/;<br>
 s/^Phone:.*\n//;<br>
 s/^Date:.*/Date: $date/;<br>
 print;<br>
}</p>
<p>3. split and join<br>
my $x=&quot;4,6,8,10,12&quot;;<br>
my @values = split /:/, $x; # the string in // can be regular patterns. now we get @values as list (4,6,8,10,12);<br>
my $z = join &quot;-&quot;, @values;  # now we get $z as a scalor &quot;4-6-8-10-12&quot;</p>
<p>4. useful m// in list context:<br>
we often use m// in list context to return the matching strings list!! (or we can say, to extract what we want out of the target string. it's simpler than $1,$2,...):<br>
eg. <br>
my($first, $second, $third) = /(\S+) (\S+), (\S+)/; # now we get the 3 matching strings in these 3 my vars<br>
my @words = /[a-z]+/ig; # now we get all matching in @words. (notice: we use g here)<br>
my %last_name = /(\w+)\s+(\w+)/g; # we use hash to store every pair of matching.</p>
<p>5. don't be too greedy:<br>
use ? after + * {3,8} ? to try to be not greedy (ie. don't try to match the maximum string)<br>
eg. we want to remove all the paired &lt;BOLD&gt;&lt;/BOLD&gt;, but keep what between them:<br>
&nbsp;&nbsp; I thought you said Fred and &lt;BOLD&gt;Velma&lt;/BOLD&gt;,not &lt;BOLD&gt;Wilma&lt;/BOLD&gt;<br>
if we use  s/&lt;BOLD&gt;(.*)&lt;/BOLD&gt;/$1/g, the result is not what expected.<br>
so we use  s/&lt;BOLD&gt;(.*?)&lt;/BOLD&gt;/$1/g, the result is what we want.</p>
<p>6. command line:<br>
(1) behave like sed: <br>
ls | perl -e 'while(&lt;&gt;){s/try/cow/;print;}'<br>
ls | perl -p -e 's/try/cow;'  # we use -p to replace the while(&lt;&gt;), which make it more like sed.<br>
(2) behave like sed -n:<br>
ls | perl -n -e 'print if s/try/cow;'</p>
<p>7. use () only for grouping, not var --- use ?:<br>
/(?:bronto)?saurus (steak|burger)/<br>
# here we add ?: before bronto, because the bronoto here is just for grouping sths togther(here we only use bronoto) to use ?. we don't want (bronto) to be $1.</p>
<p><br>
Chapter 10  More Control Structure<br>
don't need to know. recognizing them when meeting them is enough.</p>
<p><br>
Chapter 11 Perl Modules<br>
1. basic usage:<br>
just type &quot;using modules_name;&quot;, then you can use the function or objects names imported.<br>
(1) use File::Basename;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # import all names from File::Basename. eg. you can use &quot;dirname&quot; function now.<br>
(2) use File::Basename qw/ /;  # don't import functions names. you can only use these functions using full name, eg &quot;File::Basename::dirname&quot;. this allow you to use your own function with the same name.</p>
<p>2. modules introduced in this Chapter<br>
(1) File::Basename<br>
extract parts from a path name, the frequently used functions are dirname and basename<br>
eg.<br>
use File::Basename;<br>
print &quot;Please enter a filename:&quot;;<br>
chomp(my $name = &lt;STDIN&gt;);<br>
my $dirname = dirname $name;<br>
my $basename = basename $name;<br>
(2) File::Spec<br>
this module is frequently used to deal with file system related differences. for example: we don't need to care about using \ or / to seperate path parts. so if you need to write plateform-independent code, use File::Spec<br>
eg.<br>
use File::Spec;<br>
...<br>
my $new_name = File::Spec-&gt;catfile($dirname, $basename);<br>
rename($old_name, $new_name)<br>
 or warn &quot;Can't rename '$old_name' to '$new_name': $!&quot;;<br>
(3) DBI<br>
the DBI module is used to deal with DB operations. the interface is uniform.</p>
<p><br>
Chapter 12 File Tests<br>
this chapter introduce some useful functions to abtain file info<br>
1. file tests:<br>
these test flags return bool(true/false) or file info(eg. file size)<br>
eg. return type is bool <br>
if -r $filename {<br>
 ...<br>
}</p>
<p>eg. return type is size<br>
my $size = -s &quot;hello.pl&quot;;<br>
print $size;</p>
<p>eg. multiple flags<br>
if (-r $file and -w $file) {<br>
 ...<br>
}<br>
(refer to P180 for all test flags)</p>
<p>2. stat and lstat:<br>
we use them to abtain inode info about the file( lstat for link file)<br>
eg. <br>
my($dev, $ino, $mode, $nlink, $uid, $gid, $rdev,<br>
&nbsp;&nbsp;  $size, $atime, $mtime, $ctime, $blksize, $blocks)<br>
 = stat($filename);</p>
<p>3. time<br>
we use time to get current timestamp, use localtime to convert timestamp to human readable localtime, and use gmtime to convert timestamp to human readable Universal Time(Greenwich Mean Time).<br>
my $timestamp = time;<br>
my $date = localtime $timestamp;  # scalar context: Fri Jul 24 15:43:40 2009<br>
my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst)<br>
  = localtime $timestamp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # list context<br>
(notice: if using localtime and gmtime without params, they use the current timestamp by default.)</p>
<p>4. Bitwise Operators:<br>
&amp;, |, ^, &lt;&lt;, &gt;&gt;, ~&nbsp;&nbsp;  they are the same as C.</p>
<p> </p>
<p>Chapter 13 Directory Operations<br>
this Chapter just tell us: perl supplies many Unix API functions(most of them is with the same name!!)<br>
so we don't need to check them one by one. If we need an operation, just use the Unix API/command <br>
name to look up in the perldoc.<br>
eg.<br>
1. chdir &quot;/etc&quot; or die &quot;cannot chdir to /etc: $!&quot;;<br>
2. shell globbing:<br>
foreach $arg (@ARGV) {<br>
 print &quot;one arg is $arg\n&quot;;<br>
}<br>
the result of running &quot;./perl_script *.pm &quot; in shell line:<br>
one arg is barney.pm<br>
one arg is dino.pm<br>
one arg is fred.pm<br>
one arg is wilma.pm<br>
3. perl globbing:<br>
use &quot;glob&quot; operator:<br>
eg. <br>
# use space to seperate patterns. here we seperate .*(.files) and * (all other files)<br>
my @all_files_including_dot = glob &quot;.* *&quot;;  # without dir, .* and * refer to files in current path.<br>
my @all_files_including_dot = &lt;.* *&gt;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # &lt;&gt; is another syntax to do perl globbing<br>
4. rename<br>
foreach my $file (glob &quot;*.old&quot;) {<br>
 my $newfile = $file;<br>
 $newfile =~ s/\.old$/.new/;<br>
 if (-e $newfile) {<br>
&nbsp;&nbsp; warn &quot;cannot rename $file to $newfile: $newfile exist\n&quot;;<br>
 }elsif (rename $file, $newfile) {<br>
&nbsp;&nbsp; #success, do nothing<br>
 }else {<br>
&nbsp;&nbsp; warn &quot;rename $file to $newfile failed: $!\n&quot;;<br>
 }<br>
}<br>
5. $$ is the PID<br>
my $temp_dir = &quot;/tmp/scratch_$$&quot;;  <br>
6. other functions:<br>
mkdir &quot;fred&quot;, 0755 or warn &quot;cannot make fred dir: $!&quot;<br>
opendir, readdir, closedir<br>
File::Find (like unix find command)  --- very good!!! if you want to do recursive dir work.<br>
unlink, rmdir, rmtree (eg. unlink glob &quot;*.o&quot;;)<br>
link, symlink<br>
chmod 0755, &quot;fred&quot;<br>
chown $user,$group,glob &quot;*.o&quot;<br>
utime ( it's used to change timestamp of file, access, modification time)</p>
<p> </p>
<p>Chapter 14 Strings and Sorting<br>
perl supplies us with some string manipulating functions to ease the string operation instead of Regular Expression.<br>
1. Strings manipulation:<br>
my $where1 = index($stuff, &quot;wor&quot;);<br>
my $where2 = index($stuff, &quot;wor&quot;, $where1+1);<br>
my $last_slash = rindex(&quot;/etc/passwd&quot;, &quot;/&quot;);&nbsp;&nbsp;&nbsp;  # value is 4<br>
my $part = substr($string, $init_position, $length);<br>
my $out = substr(&quot;string&quot;, -3, 2);&nbsp;&nbsp;&nbsp;  # value is &quot;in&quot;<br>
substr(&quot;$string&quot;, 0, 5) = &quot;Goodbye&quot;&nbsp;&nbsp;  # cool! the substr can be replaced like this.<br>
substr($string, -20) =~ s/fred/barney/g;&nbsp;&nbsp;  # use substr to restrict the RE to work in the last 20 chars<br>
my $date_tag = sprintf &quot;%4d/%02d/%02d %2d:%02d:%02d&quot;, $yr, $mo, $da, $h, $m, $s;<br>
my $money = sprintf &quot;%.2f&quot;, 2.49997;</p>
<p>good example:<br>
# this line uses loop and regular expression to add , between every 3 digits, cool!!<br>
1 while $number =~ s/^(-?\d+)(\d\d\d)/$1,$2/;</p>
<p>2. Sorting:<br>
before we simply use &quot;sort&quot; function, here we talk about the advance use of &quot;sort&quot;.<br>
usage:<br>
  sort fun @list<br>
here fun is the function you define yourself which takes the same effect as &quot;function object&quot; in C++ STL algorithm method.<br>
this book give 2 example to illustrate the use of advanced sort. They are &quot;sorting a hash by value&quot; (we can just sort keys in normal use), and &quot;sorting by multiple keys&quot;</p>
<p> </p>
<p>Chapter 15 Smart Matching and given-when<br>
1. Smart Matching:<br>
It's too powerful! because if you use ~~, the perl will decide how to compare the left and the right operands.<br>
In the condition of comparing each items in hash or list to a pattern, etc. it will save your effert by typing just one line!!!!<br>
look for the table 15-1 in P224 to see how to use ~~<br>
eg.<br>
(1) array comparasion:<br>
use 5.010;<br>
say &quot;The arrays have the same elements!&quot; if @names1 ~~ @names2; # traditionally we have to use a loop to compare.<br>
(2) finding hash key matching RE:<br>
use 5.010;<br>
say &quot;I found a key matching 'Fred'&quot; if %names ~~ /Fred/;&nbsp;&nbsp;  # traditionally we have to use a loop to compare.</p>
<p>2. given-when -- the C switch equivalent:<br>
it's more powerful than switch, because you can do any comparison in the when block.<br>
NOTICE: break is implicitly added. so if you want to &quot;fall down&quot;, add &quot;continue&quot; manually.<br>
eg.<br>
use 5.010;<br>
given( $ARGV[0] ) {<br>
 when( /fred/i ) &nbsp;&nbsp;  { say 'Name has fred in it'; continue;}&nbsp;&nbsp;&nbsp;  # RE<br>
 when( 'Fred' )  &nbsp;&nbsp;  { say 'Name is Fred'}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # string<br>
 when( ! 'Fred' ) &nbsp;&nbsp;  { say 'Name is not Fred'}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # use !<br>
 when( $_ ~~ /^Fred/ ) { say 'Name is Fred'}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # $_ is explicitly used<br>
 when( $_ &gt; 10 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  { say 'Number is less than 10'}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # &gt; is used<br>
 when( sub($_) )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  { say 'Number is cool!'}&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;  # we can use sub here<br>
 when( 1 == 1 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  { say 'I don't see a Fred'}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # we can use anything here<br>
 default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;  { say &quot;I don't see a Fred&quot;}<br>
}</p>
<p>3. foreach-when:<br>
this structure is used when there are many items to be processed by given-when.<br>
eg. <br>
use 5.010;<br>
foreach ( @names ) { # don't use a named variable!<br>
 when( /fred/i ) { say 'Name has fred in it'; continue }<br>
 when( /^Fred/ ) { say 'Name starts with Fred'; continue }<br>
 when( 'Fred' )  { say 'Name is Fred'; }<br>
 default &nbsp;&nbsp; { say &quot;I don't see a Fred&quot; }<br>
}</p>
<p> </p>
<p><br>
Chapter 16 Process Management<br>
1. system<br>
it create a child process and then wait for its ending.(if we add &amp; after command, the father won't wait)<br>
the &quot;system&quot; function in perl has two version:<br>
(1) the single argument version:<br>
system $command_line;&nbsp;&nbsp;  # shell is automatically called to process $command_line.<br>
eg.<br>
! system &quot;rm -rf files_to_delete&quot; or die &quot;something went wrong&quot;;<br>
(2) the multiple argument version:<br>
system &quot;/bin/sh&quot;, &quot;-c&quot;, $command_line;&nbsp;&nbsp;  # the command &quot;/bin/sh&quot; is called by system with arguments.<br>
(this version doesn't call shell automatically, it just call the first argument which is a command)</p>
<p>2. exec<br>
use the command to replace the current process.<br>
eg.<br>
exec &quot;date&quot;;<br>
die &quot;date couldn't run: $!&quot;;</p>
<p>3. environment variables:<br>
actually, when we envoke perl from shell, the PATH and other env vars are inherited by perl.<br>
the vars are stored in %ENV hash.<br>
we can change it before we launch new process to affect the child.<br>
eg.<br>
$ENV{'PATH'} = &quot;/home/rootbeer/bin:$ENV{'PATH'}&quot;;<br>
delete $ENV{'IFS'};<br>
my $make_result = system &quot;make&quot;;</p>
<p>4. using Backquotes:<br>
NOTICE: `` in perl will return scalar or list according to the enviroment!!! <br>
foreach (`who`) {<br>
 my($user, $tty, $date) = /(\S+)\s+(\S+)\s+(.*)/;<br>
 $ttys{$user} .= &quot;$tty at $date\n&quot;;<br>
}</p>
<p>5. the popen equivalent:<br>
it's very useful to do piping between perl and system command!!!!<br>
just use command as the file name, adding | after or before it.<br>
then we get two running process with pipe relationship.<br>
eg.<br>
open DATE, &quot;date|&quot; or die &quot;cannot pipe from date: $!&quot;;<br>
open MAIL, &quot;|mail merlyn&quot; or die &quot;cannot pipe to mail: $!&quot;;</p>
<p>remember to close it after reading or writing.</p>
<p>6. dirty things:<br>
if you want to use raw fork and signal, check this section</p>
<p> </p>
<p><br>
Chapter 17. Some Advanced Perl Techniques<br>
1. trapping errors with eval<br>
the &quot;eval&quot; is used to trap(or register) fatal errors. <br>
the difference is:<br>
if you use eval, the program will continue to run when fatal errors happens.<br>
I found it no use for me.</p>
<p>2. grep items from a list:<br>
syntax: <br>
the first param is a {} which contain a bool expression which returns true or false. <br>
the second param is a list.<br>
if {} return true, the item will be included.<br>
eg. <br>
my @odd_numbers = grep { $_ % 2 } 1..1000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # get odd numbers from list<br>
my @matching_lines = grep { /\bfred\b/i } &lt;FILE&gt;; # get lines containing fred from file</p>
<p>3. transform items from a list to another list:<br>
we use map to do change to every item and store them in a new list. <br>
the syntax is much the same as the grep.<br>
eg. here the function &amp;big_money is used to change a item<br>
my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95);<br>
my @formatted_data = map { &amp;big_money($_) } @data;</p>
<p>4. slices: -- powerful sub list !!!<br>
the 3 kinds of slices below are all list.<br>
(1) split slices:<br>
before we use split to split a line into several fields storing in a list.<br>
but actually we just wanna one or some fields of the string, we can simply add [ ] after the split:<br>
eg.<br>
my($card_num, $count) = (split /:/)[1, 5];  # here we get the 1st and the 5th item<br>
(2) array slices:<br>
we just wanna to refer to some fields of a array:<br>
eg.<br>
my @numbers = ( @names )[9, 0, 2, 1, 0];&nbsp;&nbsp;  # we can omit the () here:  @names[9, 0, 2, 1, 0];<br>
@names[2, 3] = (&quot;cow&quot;, &quot;sheep&quot;);<br>
(3) hash slices:<br>
eg.<br>
my @three_scores = @score{ qw/ barney fred dino/ };<br>
NOTICE: hash slice is a list! so we use @ here to indicate we have a list</p>
<p> </p>
<p>Appendix B. Beyond the LIama<br>
this part tells us what else can perl do! very exciting.<br>
1. Some Important Modules<br>
CGI Cwd Fatal File::Basename File::Copy File::Spec Image::Size Net::SMTP POSIX Sys::Hostname Text::Wrap Time::Local DBI Getopt::Long Getopt::Std<br>
2. the rest:<br>
so many field!</p>
<p><br>
 </p> <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/5c686703393f62e509fa9317.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/5c686703393f62e509fa9317.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-19  17:17</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/5c686703393f62e509fa9317.html</guid>
</item>

<item>
        <title><![CDATA[Learning Perl 5th edition (perl 5.10) - part 1]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/304c8bd5feda62cd50da4b12.html]]></link>
        <description><![CDATA[
		
		<p>Tips:<br>
1. Getopt::Long<br>
Getopt::Long module is used to parse both long and short options names. It's a replacement for Getopt::Std which only support single char options. The equivalent in Unix is getopt_long and getopt function.<br>
Rules:<br>
(1) Getopt won't force user to supply any option:<br>
this means user can omit all options, and Getopt won't complain anything.<br>
(2) Getopt only force the right format if options are supplied by user:<br>
this means if user supplies options, the format must be right. (eg. it must have value or not)<br>
(3) the default value is assigned by yourself in front of using GetOptions.<br>
this means, you have to define variables used to hold the options' values first, and do initialization yourself if you want. Getopt don't supply any method to assign default values to these variables.<br>
eg.<br>
#!perl<br>
use strict;<br>
use Getopt::Long; # import the namespace</p>
<p>sub usage<br>
{<br>
print &quot;$!&quot;;<br>
print &quot;Usage: read the code yourself:)&quot;;<br>
exit(0);<br>
}</p>
<p># here we define variables and initializations. variables without initialization has &quot;undefined&quot; values.<br>
my $o_help;<br>
my $o_name = &quot;sheep&quot;;<br>
my $o_age = 10;<br>
my @o_lib;<br>
my %o_pair;<br>
Getopt::Long::Configure(qw/no_auto_abbrev/); # we don't need abbrevation(eg. --hel for --help)<br>
GetOptions('help|h' =&gt; \$o_help,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # use | to supply alternative option names<br>
&nbsp;&nbsp;&nbsp;&nbsp;  'name=s' =&gt; \$o_name,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # is = is used ,the option must has value. s indicate string <br>
&nbsp;&nbsp;&nbsp;&nbsp;  'age=i' =&gt; \$o_age,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # is expected while i indicate integer is expected.<br>
&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  'lib=s' =&gt; \@o_lib,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # use array if you have &quot;--lib lib1 --lib lib2 --lib lib3&quot;<br>
&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;  'pair=s' =&gt; \%o_pair) or &amp;usage(); # use hash if you have &quot;--pair sheep=10 --pair cow=20</p>
<p>if (defined($o_help)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  # if user doesn't supply &quot;help&quot; option, the variable is undefined<br>
print &quot;o_help: $o_help\n&quot;;<br>
}<br>
if (defined($o_name)) {<br>
print &quot;o_name: $o_name\n&quot;;<br>
}<br>
if (defined($o_age)) {<br>
print &quot;o_age: $o_age\n&quot;;<br>
}<br>
if (defined(@o_lib)) {<br>
print &quot;o_lib: @o_lib\n&quot;;<br>
}<br>
if (defined(%o_pair)) {<br>
print &quot;o_pair: &quot;, %o_pair, &quot;\n&quot;;<br>
}</p>
<p>2. how to print Usage: -- using Here Documents:<br>
&quot;here documents&quot; is to prepare command/text lines needed at a time which're used by shell to feed the application one line each time the app needs input.<br>
so it can be used to automatically interact with the interactive application.<br>
eg. <br>
sub usage<br>
{<br>
print(&lt;&lt;&quot;USAGE&quot;);&nbsp;&nbsp;  # I can't believe print can use Here Document!!!<br>
tellme Version:0.1, Copyright (C) 2009 ThomsonReuters.<br>
the analysis result is stored in internal result_table.<br>
the options given below is designed to print the table in various way.<br>
and the default behavior is to output all kinds of tables.</p>
<p>Usage: tellme.pl &lt;options&gt;<br>
--help<br>
&nbsp;&nbsp;&nbsp;  show this usage.<br>
--raw-table<br>
&nbsp;&nbsp;&nbsp;  output the raw internal result_table.<br>
--idn-non-enum-fields-table1 | -a<br>
&nbsp;&nbsp;&nbsp;  output all IDN's fields which are defined as non-enum type.<br>
--idn-non-enum-fields-table2 | -b<br>
&nbsp;&nbsp;&nbsp;  output all IDN's fields which are defined in DB..xsd file as enum type,<br>
but redefined in FieldType.xsd file as non-enum type.<br>
--idn-equals-db-enum-table1 | -c<br>
&nbsp;&nbsp;&nbsp;  output all IDN's enum fields which have the same fields as db's.<br>
--idn-equals-db-enum-table2 | -d<br>
&nbsp;&nbsp;&nbsp;  the simple version of --idn-equals-db-enum-table1.<br>
--idn-unequals-db-enum-table1 | -e<br>
&nbsp;&nbsp;&nbsp;  output all IDN's enum fields which have different fields as db's.<br>
--idn-unequals-db-enum-table2 | -f<br>
&nbsp;&nbsp;&nbsp;  the simple version of --idn-unequals-db-enum-table1.<br>
--idn-enum-not-found-in-db&nbsp;&nbsp;&nbsp;  | -g <br>
&nbsp;&nbsp;&nbsp;  output the IDN's enum fields which can not be found in db. <br>
--verbose<br>
&nbsp;&nbsp;&nbsp;  output the header line.<br>
USAGE<br>
exit(0);<br>
}</p>
<p>3. complex type - using hash and array<br>
--- general rule: ---<br>
(1) we can use &quot;${}[]&quot; to access elements of complex type:<br>
eg. $hash{$key}[$i] # hash of array<br>
$hash{$key}{key2}&nbsp;&nbsp;&nbsp;  # hash of hash<br>
(2) use @{} and %{} to indicate the content in {} is array or hash:<br>
then you can use it as an array or hash name to refer to its elements use [] or {} as usual.<br>
eg. we cat use them when list or hash is expected (eg. after &quot;foreach&quot;):<br>
foreach my $value (@{$hash{$key}}) ... # @{} indicates $hash{$key} is an array<br>
foreach my $key (keys %{$HoH{$login}}) ... # %{} indicates $HoH{$login} is a hash</p>
<p>--- use hash of hash: ---<br>
eg. processing the /etc/passwd file<br>
(1) create hash of hash:<br>
my ( $login, $p, $uid, $gid, $gecos, $dir, $s );<br>
my %HoH = ();<br>
my $file = '/etc/passwd';<br>
open( PASSWD, &quot;&lt; $file&quot; ) or die &quot;Can't open $file : $!&quot;;<br>
while( &lt;PASSWD&gt; ) {<br>
&nbsp;&nbsp;  ( $login, $p, $uid, $gid, $gecos, $dir, $s ) = split( ':' );<br>
<br>
&nbsp;&nbsp;  $HoH{ $login }{ 'uid' } = $uid;<br>
&nbsp;&nbsp;  $HoH{ $login }{ 'gid' } = $gid;<br>
&nbsp;&nbsp;  $HoH{ $login }{ 'dir' } = $dir;<br>
}<br>
close PASSWD;</p>
<p>yes, we have other style:<br>
$HoH{$login} = {&nbsp;&nbsp;&nbsp;&nbsp;  # NOTICE: { } must be used instead of () !!!!<br>
&quot;uid&quot; =&gt; $uid,<br>
&quot;gid&quot; =&gt; $gid,<br>
&quot;dir&quot; =&gt; $dir<br>
};<br>
(2) access hash of hash:<br>
method 1: you know the column name of sub hash.<br>
&nbsp;&nbsp;&nbsp;  foreach my $login ( keys %HoH ) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  $uid = $HoH{$login}{&quot;uid&quot;};&nbsp;&nbsp;&nbsp;&nbsp;  <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  $gid = $HoH{$login}{&quot;gid&quot;}; <br>
&nbsp;&nbsp;  $dir = $HoH{$login}{&quot;dir&quot;}; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  print &quot;uid: $uid, gid: $gid, dir, $dir.\n&quot;;<br>
&nbsp;&nbsp;&nbsp;  }<br>
method 2: you know nothing about the keys.<br>
foreach my $login (keys %HoH) {<br>
&nbsp;&nbsp;  foreach my $key (keys %{$HoH{$login}}) {<br>
&nbsp;&nbsp;&nbsp;  print &quot;$hash{$login}{$key}\n&quot;;<br>
&nbsp;&nbsp;  }<br>
}</p>
<p>--- use hash of array ---<br>
(1) create hash of array:<br>
my %hash;<br>
$hash{&quot;one&quot;} = [1, 2, 3];&nbsp;&nbsp;&nbsp;  # we use [] instead of () to construct list here !!!!<br>
$hash{&quot;two&quot;} = [&quot;cow&quot;, &quot;cat&quot;, &quot;sheep&quot;];<br>
(2) access hash of array:<br>
method 1: you use foreach to access the array members.<br>
foreach my $key (keys %hash) {<br>
foreach my $value (@{$hash{$key}}) {<br>
&nbsp;&nbsp;  print &quot;$value\n&quot;;<br>
}<br>
}<br>
method 2: you wanna use index to access the array members.<br>
foreach my $key (keys %hash) {<br>
for (my $i = 0; $i &lt; @{$hash{$key}}; $i++) {<br>
&nbsp;&nbsp;  print $hash{$key}[$i].&quot;\n&quot;;<br>
}<br>
}</p>
<p>--- use array of array ---<br>
(1) create array of array:<br>
## we can use push or = to assign sub array into the array. <br>
## NOTICE: we use [] instead of () to construct list here !!!!<br>
push @result_table, [ $key, &quot;-&quot;, $value_count, &quot;-&quot; ];<br>
$result_table[1] = [ 1, 2, 3, 4 ];<br>
my @AoA = (<br>
[ &quot;fred&quot;, &quot;barney&quot; ],<br>
[ &quot;george&quot;, &quot;jane&quot;, &quot;elroy&quot; ],<br>
[ &quot;homer&quot;, &quot;marge&quot;, &quot;bart&quot; ],<br>
);<br>
for $i ( 1 .. 10 ) {<br>
@tmp = somefunc($i);<br>
$AoA[$i] = [ @tmp ];<br>
}<br>
(2) access array of array:<br>
method 1: use foreach to access the subarrays:<br>
foreach my $sub_array (@array) {<br>
foreach my $value (@{$sub_array}) {<br>
&nbsp;&nbsp;  print &quot;$value\n&quot;;<br>
}<br>
}<br>
method 2: use index to access members:<br>
for (my $i = 0; $i &lt; @array; $i++) {<br>
for (my $j = 0; $j &lt; @{$array[$i]}; $j++) {<br>
&nbsp;&nbsp;  print &quot;$array[$i][$j]\n&quot;;<br>
}<br>
}<br>
method 3: mixture of foreach and index<br>
foreach my $sub_array (@array) {<br>
for (my $j = 0; $j &lt; @{$sub_array}; $j++) {<br>
&nbsp;&nbsp;  print &quot;@{$sub_array}[$j]\n&quot;;<br>
}<br>
}</p>
<p>4. loop control:<br>
last = break;<br>
next = continue;<br>
redo = goto front;</p>
<p>5. popular function error check styles:<br>
guild: $! seems always holds error msg for functions and system commands.It will remains the same if no more errors happen in the following function calling like error in POSIX C. $? only holds command return codes, but it will change in each function call to hold return code. and $@ only holds msg for fatal errors, ie. some functions or operations will cause your program to exit without giving you the chance to handle. In this case, only eval block can stop your program from exiting and store the error msg in $@. The mkpath below is an example. NOTICE: $@ only has msg for fatal errors(errors that cause your program to exit without giving you the ability to handle)<br>
(1) &quot;if + $!&quot; or &quot;or + $!&quot;<br>
if (! chdir &quot;/etc&quot;) { # the function will return true if successfully returned.<br>
die &quot;cannot chdir to /etc: $!&quot;;<br>
}<br>
chdir &quot;/etc&quot; or die &quot;cannot chdir to /etc: $!&quot;;<br>
(2) $? contains the recent `` system() or pipe 's return status code (the number)<br>
$result = `ls`;<br>
print &quot;return code: $?&quot; if $?;<br>
(3) eval + $@<br>
my $path = &quot;Yaf:/cow/sheep/cat/&quot;; # incorrect path name<br>
eval {<br>
mkpath($path,0,0755);<br>
};<br>
print &quot;mkpath error: $@&quot; if $@;</p>
<p>6. platform-independent file/folder operations:<br>
(1) to create embeded directories:<br>
use File::Path;<br>
my $path = &quot;cow/sheep/cat/&quot;; # create dirs under current dir<br>
eval {<br>
mkpath($path,0,0755);<br>
};<br>
print &quot;mkpath error: $@&quot; if $@;<br>
(2) use File::Basename and File::Spec to cover :\ \ or / issues:<br>
don't deal with :\ \ or / things yourself in file path processing, use functions provided by File::Basename and File::Spec module to cover all related issues.<br>
(3) use File::Copy to copy files<br>
copy(&quot;name_age.txt&quot;, &quot;name.txt&quot;) or die &quot;cannot copy: $!\n&quot;;<br>
<br>
7. text process related:<br>
(1) upper, lower case:<br>
uc() to uppercase<br>
lc() to lowercase</p>
<p>8. m//g will do match many times !!<br>
eg.<br>
my %last_name = /(\w+)\s+(\w+)/g; &nbsp;&nbsp;  # store every pair of matching.<br>
while( $line =~ /\(/g ) { $left++; } # find the count of '(' in current line</p>
<p>9. use modules:<br>
if you put modules under Y:\lib\, say GPC\MLS\COMMON.pm, you should invoke perl like this:<br>
perl -IY:\lib\ script.pl, <br>
and in script.pl you should write like this:<br>
use GPC::MLS::COMMON;</p> <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/304c8bd5feda62cd50da4b12.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/304c8bd5feda62cd50da4b12.html#comment">查看评论</a>]]></description>
        <pubDate>2009-08-18  17:41</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/304c8bd5feda62cd50da4b12.html</guid>
</item>

<item>
        <title><![CDATA[vim 简明完全手册 cool~~]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/0a10cedf0574991a485403e3.html]]></link>
        <description><![CDATA[
		
		一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  对vim配置文件的编辑：<br>
:scriptnames&nbsp;&nbsp;  发现配置文件的位置<br>
:edit ~/.vimrc  编辑该配置文件<br>
vim说明文件的阅读：<br>
CTRL-] 跳转到当前光标所在单词对应的主题<br>
CTRL-O 回到前一个位置<br>
复制一个样板vimrc文件（unix）：<br>
:!cp -i $VIMRUNTIME/vimrc_example.vim ~/.vimrc<br>
复制一个样板vimrc文件：<br>
:set compatible?<br>
查看vim配置文件的所在位置：<br>
:scriptnames 或 :version<br>
拷贝vimtutor，并重命名：<br>
vim -u NONE -c `e $VIMRUNTIME/tutor/tutor.cn` -c `w! TUTORCOPY` -c `q`<br>
vim -u NONE -c &quot;set nocp&quot; TUTORCOPY<br>
 <br>
会话保存了整个Vim的外观. 视图保持一个窗口的属性<br>
:mkview [num] &quot;保存当前窗口的视图,num可以是1－9&quot;<br>
:loadview [num] &quot;载入上次保存的视图,num可以是1－9&quot;<br>
:mkview ~/.vim/main.vim &quot;保存当前的文件的视图到文件&quot;<br>
:source ~/.vim/main.vim &quot;载入已存在的试图文件&quot;<br>
:set viminfo=string &quot;string指代你要保存的东西. 其语法是一个选项字符跟一个参数. 一对对的选项/参数以逗号分隔&quot;,可用选项有：<br>
: 要保存的冒号命令历史记录数<br>
@ 要保存的输入历史记录数<br>
/ 要保存的搜索命令历史记录数<br>
r 可移动介质, 对此不会保存其标记信息(可以多次使用)<br>
! 以大写字母开始并且不含有任何小写字母的全局变量<br>
h 开始时禁用°hlsearch°选项<br>
% 缓冲区列表(只有没指定文件参数启动Vim时才会恢复这些信息)<br>
c 使用°encoding°选项中的方法进行字符编码转换<br>
n viminfo文件的名字(必需是最后一个选项)<br>
在Vim中用&quot;:wviminfo&quot;和&quot;:rviminfo&quot;命令来保存和恢复这些信息，<br>
:wviminfo! ~/tmp/viminfo &quot;保存一个viminfo的信息&quot;<br>
:rviminfo! ~/tmp/viminfo &quot;读取一个viminfo的信息，这样可用把其他文件的viminfo那来用&quot;<br>
:mksession vimbook.vim &quot;创建一个会话文件&quot;<br>
:source vimbook.vim &quot;恢复一个会话状态&quot;<br>
vim -S vimbook.vim &quot;启动Vim时恢复某个会话&quot;<br>
sessionoptions 选项的设置如下，如：:set sessionoptions+=resize &quot;恢复Vim窗口的大小&quot;<br>
blank 空窗口<br>
buffers 所有的缓冲区, 而不仅是当前窗口中的<br>
curdir 当前目录<br>
folds folds, 包括手工创建的<br>
help 帮助窗口<br>
options 所以的选项和键映射<br>
winsize 窗口大小<br>
========================================================================================<br>
二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在普通模式下<br>
移动光标：<br>
h 左&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  j 下&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  k 上&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  l 右<br>
gj 下，长字符串行折行时只移动下一个屏幕显示行<br>
gk 上，长字符串行折行时只移动下一个屏幕显示行<br>
w (小)向后（右）移动一个word,光标在word的首字母处，如3w，向后移动3个word<br>
b (小)向前（左）移动一个word,光标在word的首字母处,如3b，向前移动3个word<br>
e (小)向后（右）移动一个word,光标在word的尾字母处，如3e，向后移动3个word<br>
ge (小)向前（左）移动一个word,光标在word的尾字母处,如3ge，向前移动3个word<br>
W （大）向后（右）移动一个word,光标在word的首字母处，如3w，向后移动3个word，但忽略其他边界字符<br>
B （大）向前（左）移动一个word,光标在word的首字母处,如3b，向前移动3个word，但忽略其他边界字符<br>
E （大）向后（右）移动一个word,光标在word的尾字母处，如3e，向后移动3个word，但忽略其他边界字符<br>
gE （大）向前（左）移动一个word,光标在word的尾字母处,如3ge，向前移动3个word，但忽略其他边界字符<br>
$ （shift 4）移动到当前行行尾，同&lt;End&gt;功能键，可以使用&ldquo;2$&rdquo;记数,移动到下一行的行尾<br>
^ （shift 6）移动到当前行的第一个非空白字符上，不接收记数移动<br>
0 （数字）移动到当前行的第一个字符上，同&lt;Home&gt;功能键，不接收记数移动<br>
f （小）向后（右）搜索某一单字符，光标在被搜索字符上，如&ldquo;fy&rdquo;，搜索下一个字符y的所在，可用&ldquo;;&rdquo;向后重复查讯，用&ldquo;,&rdquo;向前重复查讯<br>
F （大）向前（左）搜索某一单字符，光标在被搜索字符上，如&ldquo;Fy&rdquo;，搜索上一个字符y的所在，可用&ldquo;;&rdquo;向后重复查讯，用&ldquo;,&rdquo;向前重复查讯<br>
t （小）向后（右）搜索某一单字符，光标在被搜索字符前，如&ldquo;ty&rdquo;，搜索下一个字符y的所在，可用&ldquo;;&rdquo;向后重复查讯，用&ldquo;,&rdquo;向前重复查讯<br>
T （大）向前（左）搜索某一单字符，光标在被搜索字符前，如&ldquo;Ty&rdquo;，搜索上一个字符y的所在，可用&ldquo;;&rdquo;向后重复查讯，用&ldquo;,&rdquo;向前重复查讯<br>
% 跳转到与当前光标下的括号相匹配的字符上记数+% 跳转到正文的某个部分，如&quot;50%&quot;将会把光标定位在文件的中间<br>
gg 跳转到第一行<br>
G 跳转到最后一行，可用&quot;23G&quot;等跳转到指定的行<br>
H 跳转到本屏幕的开始<br>
M 跳转到本屏幕的中间<br>
L 跳转到本屏幕的结尾<br>
zz 把当前行置为屏幕正中央<br>
zt 把当前行置于屏幕顶端<br>
zb 把当前行置于屏幕底端<br>
删除字符：<br>
x （小）删除一个字符，&quot;4x&quot;删除4个字符<br>
d (小) 后跟任何一个位移命令, 它将删除从当前光标起到位移的终点处的文本内容，如：dd 删除一行字符，dw 删除一个word,&quot;d4w&quot;删除4个word,&quot;d2e&quot;删除2个word到词尾,&quot;d$&quot;删除自当前光标到行尾的内容.<br>
c (小)删除一个word后并进入Insert模式，如：cc 删除一行后并插入一行（同&quot;c$&quot;）<br>
r 输入一个字符用以替换当前光标下的那个字符<br>
J （大）删除一个换行符<br>
u （小）撤销操作<br>
CTRL-R 重做（反转撤消动作）<br>
U （大）撤销上一次的操作，包括对自己的上次操作<br>
快捷方式：<br>
x 代表dl(删除当前光标下的字符)<br>
X 代表dh(删除当前光标左边的字符)<br>
D 代表d$(删除到行尾的内容)<br>
C 代表c$(修改到行尾的内容)<br>
s 代表cl(修改一个字符)<br>
S 代表cc(修改一整行)<br>
编辑命令：<br>
i （小）在当前光标之前插入文本<br>
a （小）在当前光标之后插入文本<br>
o （小）当前行的下面插入新一行<br>
O （大）当前行的上面插入新一行<br>
9k 上移9行，其他命令也可用数字＋命令的方式实现，重复的编辑操作<br>
ZZ （大）保存当前文件并退出<br>
放弃编辑：<br>
:q! 放弃所有的修改并退出<br>
:e! 放弃所有修改并重新载入该文件的原始内容<br>
求助：<br>
:help 得到帮助文件的起始点,等同于F1功能键<br>
:help {subject} 得到某个特殊主题的帮助，如：:help CTRL-A，查看关于CTRL-A的帮助<br>
:help `command` 得到关于某个选项的帮助,如:help `number`<br>
:help E37 得到某个错误ID号的帮助<br>
三、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  小技巧：<br>
交换两个字母，&ldquo;xp&rdquo;<br>
光标在字母时中间，删除整个单词，&ldquo;daw&rdquo;; 并可以用&ldquo;.&rdquo;重复操作来删除整个单词。&ldquo;daw&rdquo;即&ldquo;Delete A Word&rdquo;<br>
修改整句话，即删除整句后加入一个空行，不包含句子后面的空格（是&quot;Inner Sentence&quot;的缩写），&ldquo;cis&rdquo;<br>
修改整句话，即删除整句后加入一个空行，包含了句子后面的空格（是&quot;a Sentence&quot;的缩写），&ldquo;cas&rdquo;<br>
修改整句话，即删除整句后加入一个空行，包含了句子后面的空白，&ldquo;das&rdquo;<br>
用v进入visual模式，用as可以选择一个句子。<br>
%s/\&lt;oldword\&gt;/newword/gc &quot;把文件中所有的oldword替换成newword，如果没有&lsquo;c&rsquo;则就不进行提示，&quot;g&quot;标志则指示替换操作将一行中所有出现的目标字串都进行替&quot;<br>
 <br>
在filename1中打开filename2，并比较filename1和filename2<br>
:edit filename2<br>
:vertical diffsplit filename2<br>
 <br>
简单映射:使用&quot;:map&quot;命令，把一连串Vim命令以一个按键来表示。&quot;:map&quot;不带参数则列出已定义的映射。<br>
:map &lt;F5&gt; i{&lt;Esc&gt;ea}&lt;Esc&gt; &quot;在一个word的前后加上大括号&quot;其中&lt;Esc&gt;和&lt;F5&gt;为手工键入，而不是键盘上的功能键。当把一个vim功能键变为映射 键后，就失去了原有的意义，至到映射被删除。<br>
 <br>
对字符串行进行排序： <br>
第一种方法：<br>
/^firstline<br>
j<br>
:.,/^$/-1!sort<br>
说明：上面的命令首先会跳转到第一行, 即开头是&quot;firstline&quot;的行, 然后再下移一行, 用sort程序过滤自该行直至下一个空行.<br>
第二种方法：<br>
在Visual模式下选择要排序的行然后用&quot;!sort&quot;命令<br>
反转行序：<br>
:g/^/m 0<br>
说明：g是命令global，m是命令move<br>
对一串连续的行进行反转行序：<br>
:`t+1,.g/^/m `t<br>
说明：首先移到第一行并以&quot;mt&quot;标记该行.然后移到最后一行执行命令<br>
 <br>
统计文件全部内容的字数:<br>
先键入&quot;g&quot;，再用CTRL-g<br>
统计文件部分内容的字数：<br>
方法一：<br>
将光标移到要统计部分的开头处执行&quot;g CTRL-G&quot;命令, 然后移到要统计部分的末尾再用一次&quot;g CTRL-G&quot;. 计算两次命令得到的当前word位置之差, 就得到这部分内容的字数统计<br>
方法二：<br>
使用Visual模式, 选择要统计的部分. 然后用&quot;g CTRL-G&quot;.<br>
 <br>
在编辑脚本或程序时查找帮助页：<br>
光标移到要查找帮助的关键字上，然后键入&quot;K&quot;(大写)，Vim会对光标所在的词执行&quot;man&quot;程序。<br>
让man页与vim在一个窗口中显示：<br>
首先运行man对应的文件类型plugin（可以把它放到vimrc文件里）:<br>
:source $VIMRUNTIME/ftplugin/man.vim<br>
然后可以使用vim的&quot;Man&quot;命令对某些字符进行查讯帮助，如：&quot;Man 3 echo&quot;查找man页第三节中的echo,通过CTRL-W来切换当前窗口。<br>
 <br>
消除所有行尾的多余空格：<br>
:%s/\s\+$//<br>
说明：指定的行号范围是&quot;%&quot;, 即应用于每一行中. &quot;:substitute&quot;命令要查找的字串是&quot;\s\+$&quot;.这会查找位于行尾的一个或多个空白字符，&quot;:substitute&quot;命令的&quot;to&quot;部分是空内容:&quot;//&quot;. 即把此类的空白都替换为空。&nbsp;&nbsp;&nbsp;&nbsp;  <br>
查找一个word在何处被引用：<br>
编辑所有包含了&quot;frame. counter&quot;的C文件<br>
vim \VimBacktick{}grep -l frame_counter *.c\VimBacktick{}<br>
说明：&quot;-l&quot;参数, 所以该命令将只是列出包含了该词的文件名而不显示匹配的行。<br>
 <br>
如果你想查找所有C程序中的&quot;error string&quot;, 就可以用下面的命令:<br>
:grep error_string *.c<br>
说明：跳转到下一个匹配的行使用&quot;:cnext&quot;命令.跳转到前一个匹配的行可以用&quot;:cprev&quot;命令, &quot;:clist&quot;命令则可以一次列出所有的匹配<br>
注：内置的&quot;:grep&quot;命令用到了外部命令grep(Unix)或findstr(Windows).<br>
 <br>
在&quot;:&quot;号命令行中：<br>
CTRL-C或&lt;Esc&gt; 可以放弃所有已经键入的命令.<br>
&quot;CTRL-D&quot;可以列出未用&lt;tab&gt;补全的命令。<br>
&quot;CTRL-P&quot;可以向前返回已经输入过的命令，效果如同&lt;Up&gt;<br>
&quot;CTRL-N&quot;可以向后返回已经输入过的命令，效果如同&lt;Down&gt;<br>
q: 在屏幕底部打开一个命令行(小)窗口. 该窗口的内容是历史记录, 最后一行是空行。对命令行窗口作出的修改不会被保存. 历史记录不会因此被改写.<br>
 <br>
可以用CTRL-Z来挂起vim，并回到shell中，之后可用&quot;fg&quot;来回到vim中。<br>
 <br>
执行shell命令：<br>
在Vim中:<br>
:!{program} 执行{program}，如!ls,!pwd，!shell等<br>
:r !{program} 执行{program}并读取它的输出<br>
:w !{program} 执行{program}并把当前缓冲区的内容作为它的输入<br>
:[range]!{program} 以{program}过滤指定的行<br>
 <br>
vim -x exam.txt &quot;加密文件exam.txt&quot;<br>
vim -x -n file.txt &quot;加密file.txt文件，并不生成交换文件，注：Vim会把所有东西都放到内存里&quot;<br>
:setlocal noswapfile &quot;可在编辑过程中禁止使用交换文件&quot;<br>
:X &quot;（大写）设置对文件的加密&quot;<br>
:set key= &quot;停止对一个文件的加密，把`key`选项设置为一个空字串&quot;<br>
vim -b datafile &quot;编辑一个二进制文件&quot;<br>
:set display=uhex &quot;设置以十六进制格式显示不可打印字符，&quot;ga&quot;命令可以来查明当前光标下字符的本来面目&quot;<br>
g CTRL-G &quot;可以获知光标所在字符是整个文件中第几个字节&quot;<br>
2345go &quot;转到第2345个字节去&quot;<br>
使用xxd程序编辑二进制文件的过程：<br>
1 用vim -b datafile 打开二进制文件<br>
2 用&quot;:%!xxd&quot;进行十六进制格式的转储<br>
3 编辑完毕后使用&quot;:%!xxd -r&quot;反向转换，逆向转换时只有其十六进制形式被认为是有效的. 对可打印形式的改变会被转换程序忽略<br>
 <br>
:hide edit two.txt &quot;在编辑另一个文件时而又想不保存当前的文件时，可用隐藏缓冲区的编辑&quot;<br>
:buffers 或:ls &quot;列出整个缓冲区列表,&quot;<br>
列出的缓冲区列表说明如下：<br>
u 未被列出的缓冲区|unlisted-buffer|[[译: 既然未被列出你又怎么知道? :ls! % 当前缓冲区<br>
# 上一次的活动缓冲区<br>
l 被载入并显示在某窗口中的缓冲区<br>
h 被载入但隐藏的缓冲区.<br>
= 只读的缓冲区<br>
- 不可编辑的缓冲区, 其中°modifiable°选项被关闭<br>
+ 有改动的缓冲区<br>
:buffer [num] &quot;在当前窗口编辑缓冲区&quot;<br>
:sbuffer [num] &quot;打开一个并列的窗口编辑缓冲区&quot;<br>
:bdelete 3 &quot;一个缓冲区从列表中去除&quot;<br>
:bnext &quot;跳转到下一个缓冲区&quot;<br>
:bprevious &quot;跳转到前一个缓冲区&quot;<br>
:bfirst &quot;跳转到第一个缓冲区&quot;<br>
:blast &quot;跳转到最后一个缓冲区&quot;<br>
 <br>
:{range}center [width] 让一个范围的行居中<br>
:{range}right [width]  让一个范围的行右对齐<br>
:{range}left [margin] 让一个范围的行左对齐,[margin]指左边留白的宽度<br>
左右对齐的方法：<br>
1.使用宏包:runtime macros/justify.vim<br>
2.使用外部程序:%!fmt<br>
 <br>
合并多行文本：<br>
:g/./,/^$/join<br>
说明：<br>
:g/./ 一个全局命令, 查找那些至少有一个字符的行.<br>
,/^$/ 指定一个范围, 从当前行开始(非空行)直到一个空行.<br>
join &quot;:join&quot;命令把指定范围内的行连为一行.<br>
 <br>
重新格式化文件：<br>
1.先修改所要修改的内容<br>
2.用&quot;v&quot;命令进入Visual模式<br>
3.选定所要重新格式化的内容后键入&quot;gq&quot;<br>
4.其他格式化方式：&quot;gqap&quot;格式化一段文本(段以空行为分界). 包括当前光标之前的部分,&quot;gggqG&quot;格式化整个文件<br>
 <br>
dp &quot;两个文件的不同被消除了, 当前窗口中引起不同的内容被放到另一窗口中缺少这段内容的地方去了. &quot;dp&quot;是&quot;diff put&quot;的缩写&quot;<br>
将光标移到右边的窗口, 到&quot;changed&quot;插入的位置.键入命令:do<br>
vim也会消除了该位置的不同之处，&quot;do&quot;意为&quot;diff obtain&quot;<br>
 <br>
将&quot;Last, First&quot;改为&quot;First Last&quot;,使用命令：<br>
:%s/\([^,]*\), \(.*\)/\2 \1/<br>
说明：替换操作的命令参数形如&quot;/from/to/&quot;. 斜杠是用来分隔&quot;from&quot;和&quot;to&quot;的.对于&quot;from&quot;部分对应的内容:<br>
第一个部分位于\( \)之间, 对应&quot;Last&quot; \( \)<br>
匹配除逗号外的任何东西[^,]<br>
任意次重复*<br>
匹配&quot;, &quot; ,<br>
第二个部分位于\( \)之间, 对应&quot;First&quot; \( \)<br>
任意字符 &ldquo;.&rdquo;<br>
任意次重复 &ldquo;*&rdquo;<br>
在 对应&quot;to&quot;的部分我们指定了&quot;\2&quot;和&quot;\1&quot;. 这在Vim中被称作反向引用. 它们可以用来指代此前在\( \)中匹配的内容. &quot;\2&quot;指代在第二个&quot;\( \)&quot;中匹配的内容, 也就是&quot;First&quot;部分, &quot;\1&quot;则指第一个\( \)中的内容,即&quot;Last&quot; 部分.<br>
 <br>
:iabbrev ad advertisement 每次键入&quot;ad&quot;时都自动扩展为&quot;advertisement&quot;，可以用&quot;:iab&quot;代替完整的命令名&quot;:iabbrev&quot;<br>
:abbreviations 命令可以列出当前定义的所有缩写<br>
:unabbreviate + 缩写词替换词 命令可以用于删除一个缩写，但输入之后它还会再做一次替换才会生效。:abclear有同样的效果。<br>
:abbreviate errword rightword 可以更正错误的输入<br>
CTRL-V 命令可以保证你键入的下一个字符被原封不动地被录入（如特殊字符），支持ASCII，十六进制（前面加o），八进制输入（前面加x），16bit或32bit的数字（前面加u）<br>
通过输入连续的三个键&quot;CTRL-K加两个字母&quot;可以键入键盘上没有的字符，用:digraphs可以查看可用的连字符<br>
========================================================================================<br>
CRTL-G 显示正在编辑的文件的详细信息<br>
CTRL-U 使文本向下滚动半屏<br>
CTRL-D 使文本向上滚动半屏<br>
CTRL-E 使文本向上滚动一行<br>
CTRL-Y 使文本向下滚动一行<br>
CTRL-F 使文本向后滚动一整屏(实际上是整屏去两行)<br>
CTRL-B 使文本向前滚动一整屏<br>
CTRL-O 跳转到更早些时间停置光标的位置(提示: O意为older). <br>
CTRL-I 跳回到后来停置光标的更新的位置(提示: I在键盘上位于O前面，作用同&lt;Tab&gt;键）<br>
&quot;CTRL-P&quot; 对于重复的输入，按下&quot;CTRL-P&quot;, Vim会根据已经输入的部分向前寻找，补全整个词<br>
&quot;CTRL-N&quot; 对于重复的输入，按下&quot;CTRL-N&quot;, Vim会根据已经输入的部分向后寻找，补全整个词<br>
CTRL-X CTRL-F 文件名<br>
CTRL-X CTRL-L 整行内容<br>
CTRL-X CTRL-D 宏定义(也包括那些在include文件里定义的宏)<br>
CTRL-X CTRL-I 当前文件和被当前文件include的文件<br>
CTRL-X CTRL-K 来自一个字典文件的word<br>
CTRL-X CTRL-T 来自一个thesaurus的word<br>
CTRL-X CTRL-] tags<br>
CTRL-X CTRL-V Vim的命令行<br>
用`complete`选项来定制Vim在补全word时所用的策略，使用`ignorecase`选项，在搜索匹配的word时忽略大小写的不同。`infercase`. 它使搜索<br>
匹配的word时忽略剩余部分的大小写。<br>
在插入模式下，CTRL-Y会复制上一行的字母内容到当前行的光标处。<br>
在插入模式下，CTRL-E会复制下一行的字母内容到当前行的光标处。<br>
========================================================================================<br>
简单模式搜索：(使用正则表达式)<br>
^ 字符匹配一行的开头，如&quot;/^word&quot;只匹配出现在一行开头的word<br>
$ 字符匹配一行的末尾，如&quot;/word$&quot;只匹配出现在一行末尾的word<br>
注：&quot;/^the$&quot;,只会匹配到一行的内容仅包含&quot;the&quot;的情况. 有空白字符也不行<br>
. 匹配除换行符外的任何单字符，如&quot;/wo.d&quot;，&quot;.&quot;可以用&quot;\.&quot;来匹配，在normal模式下也可用来做重复的动作，<br>
 <br>
标记跳转：<br>
m{mark} 将当前光标下的位置名之为标记&quot;mark&quot;.从a到z一共可以使用26个自定义的mark. 定义后的标记不在屏幕上显示，只在Vim内部记录所代表的位置<br>
`{mark} mark就是你定义的标记的名字,如用&quot;ma&quot;标记&quot;a&quot;处，用&quot;`a&quot;跳转到标记a处<br>
` 进行此次跳转之前的起跳点<br>
`` 上次编辑该文件时光标最后停留的位置,跳回到上一个的出发点，可以在两点之间来回跳转<br>
[ 最后一次修改的起始位置<br>
] 最后一次修改的结束位置<br>
:marks 列出已经标记过的标记列表<br>
:jumps 列出曾经跳转过的位置列表<br>
/string 用于向下搜索一个字符串，用&ldquo;n&rdquo;可以继续查找下一个，用&ldquo;N&rdquo;可以继续查找上一个<br>
?string 用于向上搜索一个字符串，用&ldquo;n&rdquo;可以继续查找下一个，用&ldquo;N&rdquo;可以继续查找上一个<br>
* 把光标定位于某个word上,对当前光标所在的word向下搜索<br>
# 把光标定位于某个word上 <br>
/\&lt;word\&gt; 精确搜索单词word<br>
查找一个文件：把光标置于所要查找的文件名上，然后键入&quot;gf&quot;.当这个文件并不在工作目录下时，Vim会用在`path`选项中定义的目录去查找它. 该选项的内容是一个以逗号分隔的目录名列表,格式为：:set path+=c:/prog/include.<br>
或通过:find filename来查找。<br>
或通过&quot;:sfind&quot;命令来替代&quot;:find&quot;命令，在新窗口中打开。<br>
======================================================================================== <br>
set nocompatible &ldquo;设置默认模式为普通vim模式&rdquo;<br>
set backspace=indent,eol,start &quot;在Insert模式下退格键何时可以删除光标之前的字符. 选项中以逗号分隔的三项内容分别指定了Vim可以删除位于行首&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  的空格, 断行, 以及开始进入Insert模式之前的位置&quot;<br>
:set ignorecase 忽略大小写匹配<br>
:set noignorecase 大小写的精确匹配<br>
:set number 在每行的前面显示一个行号<br>
:set nonumber 关闭行号显示<br>
:set ruler 开启右下角的光标位置显示<br>
:set noruler 关闭右下角的光标位置显示<br>
:set hlsearch 高亮显示搜索结果<br>
:set nohlsearch 关闭高亮显示搜索结果<br>
:nohlsearch 去掉当前的高亮显示<br>
:set incsearch 在键入目标字符串的过程中就同时开始搜索<br>
:set wrapscan 搜索过程在文件内部循环进行（默认）<br>
:set nowrapscan 搜索过程在文件内部只进行一次<br>
set autoindent &quot;在开始一个新行时对该行施以上一行的缩进方式.&quot;<br>
set history=50 &quot;设置冒号命令和搜索命令的命令历史列表的长度&quot;<br>
set ruler &quot;总是在Vim窗口的右下角显示当前光标的行列信息&quot;<br>
set showcmd &quot;在Vim窗口的右下角显示一个完整的命令已经完成的部分&quot;<br>
set incsearch &quot;在键入要搜索的字串的同时就开始搜索当前已经键入的部分&quot;<br>
map Q gq &quot;定义了一个&quot;Q&quot;命令映射到&quot;gq&quot;操作符命令，进入Ex模式&quot;<br>
filetype on &quot;自动识别文件类型&quot;<br>
plugin on &quot;用文件类型plugin脚本,对某种文件类型来说最常用的选项可以放在一个Vim中叫文件类型plugin的脚本里.请参考|write-filetype-plain|&quot;<br>
indent on &quot;使用缩进定义文件,请参考jfiletype-indent-onj和°indentexpr°选项&quot;<br>
&quot;autocmd FileType text setlocal textwidth=78 &quot;<br>
autocmd FileType text &quot;是一个自动命令. 它所定义的是每当文件类型被设置为&quot;text&quot;时就自动执行它后面的命令.&quot;<br>
setlocal textwidth=78 &quot;在当前行已超过78个字符时，让Vim可以自动断行，这种设置只对当前的一个文件有效.&quot;<br>
:options &quot;打开选项帮助窗口&quot;<br>
:help `wrap` &quot;获得选项关键字的详细解释&quot;<br>
:set iskeyword&amp; &quot;恢复一个选项值的默认设置&quot;<br>
:set nowrap &quot;控制长行是否折到下一行显示的命令是&quot;<br>
:set sidescroll=10 &quot;查看左右10个字符的上下文&quot;<br>
:set whichwrap=b,s &quot;控制移动光标移动到行首或行尾时的操作，光标位于行首时按退格键会往回移动到上一行的行尾. 同时在行尾按空格键也会移动到下&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  一行的行首&quot;<br>
:set whichwrap=b,s,&lt;,&gt; &quot;左右箭头键在遇到行的边界时可以转行，在normal模式下&quot;<br>
:set whichwrap=b,s,&lt;,&gt;,[,] &quot;左右箭头键在遇到行的边界时可以转行,在Insert模式下&quot;<br>
:set list &quot;设置制表符成为可见的字符&quot;<br>
:set listchars=tab:&gt;-,trail:- &quot;使制表符以&quot;&gt;---&quot;显示, 同时行尾空格以&quot;-&quot;显示&quot;<br>
:set iskeyword<br>
<a href="mailto:iskeyword=@,48-57,_,192-255">iskeyword=@,48-57,_,192-255</a> &gt; &quot;定义了一个word中可以包含哪些字符，&quot;@&quot;在这里代指所有的字母. &quot;48-57&quot;指ASCII码从48到57的那些字符, 即0到9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &quot;192-255&quot;是可打印拉丁字母，要去除一个字符使用操作符&quot;-=&quot;，要添加一个字符使用操作符&quot;+=&quot;&quot;<br>
:syntax enable &quot;打开色彩&quot;<br>
:set background=&quot;/dark&quot; &quot;设置背景颜色为暗色（或light亮色）&quot;<br>
:colorscheme evening &quot;选择颜色方案（evening），其他颜色方案在$VIMRUNTIME/colors目录中&quot;<br>
:source $VIMRUNTIME/syntax/2html.vim &quot;把当前文件转到HTML格式&quot;<br>
:set autowrite &quot;每当需要时就自动保存，不需要过问&quot;<br>
:set noautowrite &quot;每当需要保存时，就过问&quot;<br>
:set backup &quot;生成备份文件&quot;<br>
:set backupext=.bak &quot;重新命名备份文件的后缀为.bak&quot; 备注: 如果°backup°选项是关闭的但°writebackup°选项是打开的, Vim还会生成一个备份文件. 但是, 一旦该文件被成功地保存它就会被自动删除.<br>
:set patchmode=.orig &quot;对原始文件进行备份&quot;<br>
:set backupext=.old  &quot;指定对原始文件进行备份的后缀&quot;<br>
:write &gt;&gt; logfile &quot;把当前文件的内容追加到logfile文件中&quot;<br>
:set fileformats=unix,dos &quot;Vim能自动识别的格式的集合&quot;<br>
:set fileformat? &quot;查看当前的文件格式,在vim中有三种格式，分别是：unix &lt;LF&gt;；dos &lt;CR&gt;&lt;LF&gt;和mac &lt;CR&gt;&quot;<br>
:edit ++fileformat=unix|dos|mac file.txt &quot;强制指定文件file.txt的格式为unix,dos或mac，++fileformat可荐絬为++ff&quot;<br>
把一个dos格式的文件转换成unix格式可以通过以下两步完成：<br>
:set fileformat=unix<br>
:write<br>
:set showmatch &quot;键入&quot;闭括号&quot;时显示它与前面的哪个&quot;开括号&quot;匹配,对于大，中，小括号都适用&quot;<br>
:set matchtime=15 &quot;设置键入某个闭括号时,等待时间的长短，时间单位是十分之一秒&quot;<br>
:set textwidth=30 限制每一行能有多少个字符。注：`wrap`选项使Vim能显示需要折行的过长的行, 但只是为了显示的需要, 并不在文件中实际插入一个换行符<br>
:set autoindent &quot;自动插入缩进&quot;<br>
&gt;&gt; &quot;增加一行的缩进量&quot;<br>
&lt;&lt; &quot;减少一行的缩进量&quot;<br>
:set shiftwidth=4 &quot;设置缩进量增减的单位，但会得到一个8字符的缩进，可以通过:set softtabstop=4来控制缩进&quot;<br>
:set tabstop=3 &quot;设置制表符的字符长度&quot;<br>
:retab 8 &quot;重置制表符的长度为8&quot;<br>
 <br>
========================================================================================<br>
多文本编辑：<br>
:edit otherfilename &quot;编辑另一个文件，但需要事先保存原文件&quot;<br>
:hide edit otherfilename &quot;编辑另一个文件，不需要事先保存原文件&quot;<br>
vim one.c two.c three.c &quot;启动时就指定要编辑的多个文件，使用next，next!或wnext转到下一个文件，使用pervious或wpervious转到上一个文件，使用 last转到最后一个文件，使用first转到第一个文件使用args可以查看正在编辑的文件名&quot;<br>
:args 1.c 2.h 3.h &quot;重新定义编辑的文件列表&quot;<br>
CTRL-^ &quot;跳转到刚刚编辑过的文件&quot;<br>
`&quot;&nbsp;&nbsp;  &quot;返回上次离开该文件时光标所在的位置&quot;<br>
`.&nbsp;&nbsp;  &quot;返回最后一次对文件做出改动处&quot;<br>
vim -R file 以只读方式打开文件，同&quot;view file&quot;,但可以使用!强制执行。vim -<br>
:saveas &quot;把现有的文件另存为一个新文件&quot;<br>
:winheight &quot;设置一个期望的最小的窗口高度. &quot;<br>
:winminheight &quot;设置一个强制的最小高度&quot;<br>
:winwidth &quot;指定期望的最小窗口宽度&quot;<br>
:winminwidth &quot;强制的最小窗口宽度.&quot;<br>
:equalalways &quot;在每次打开或关闭窗口Vim都自动让所有窗口均摊屏幕上可用的高度和宽度.&quot;<br>
:split &quot;分割一个窗口为两个，可以通过split newfile在新窗口中打开newfile，可以使用CTRL－W来切换当前窗口，使用CTRL-w +或-来改变窗口的大小，使用:close来关闭窗口，使用:only可以关闭除当前窗口外的其他窗口&quot;<br>
:new &quot;打开一个新窗口并开始编辑一个新的缓冲区&quot;<br>
:vsplit &quot;创建新窗口位于当前窗口的左边&quot;<br>
:vnew &quot;用于垂直分隔窗口并在其中打开一个新的空缓冲区&quot;<br>
:set scrollbind &quot;设置多窗口同步滚动&quot;<br>
:set noscrollbind &quot;取消多窗口同步滚动&quot;<br>
 <br>
CTRL-W j &quot;切换窗口到下面的窗口&quot;<br>
CTRL-W k &quot;切换窗口到上面的窗口&quot;<br>
CTRL-W h &quot;切换窗口到左边的窗口&quot;<br>
CTRL-W l &quot;切换窗口到右边的窗口&quot;<br>
CTRL-W t &quot;切换窗口到顶部窗口&quot;<br>
CTRL-W b &quot;切换窗口到底部窗口&quot;<br>
 <br>
CTRL-W K &quot;向上移动窗口&quot;<br>
CTRL-W J &quot;向下移动窗口&quot;<br>
CTRL-W H &quot;向左移动窗口&quot;<br>
CTRL-W L &quot;向右移动窗口&quot;<br>
 <br>
:qall &quot;退出所有窗口&quot;<br>
:wall &quot;保存所有窗口&quot;<br>
:wqall &quot;保存并退出所有窗口&quot;<br>
:qall! &quot;强制退出所有窗口&quot;<br>
 <br>
vim -o(小) filename1,2,3... &quot;为每个文件打开一个窗口，水平排列&quot;<br>
vim -o(大) filename1,2,3... &quot;为每个文件打开一个窗口，竖直排列&quot;<br>
vimdiff filename1 filename2 ... &quot;显示文件间的不同之处&quot;<br>
zo &quot;展开层叠显示&quot;<br>
zc &quot;收起层叠显示&quot;<br>
]c &quot;直接向前定位到下一个不同之处&quot; <br>
[c &quot;直接向后定位到下一个不同之处&quot;<br>
:diffupdate &quot;重新比较两个文件&quot;<br>
========================================================================================<br>
四、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  visual 模式 (按&quot;v&quot;可以进入Visual模式)<br>
CTRL-V 对矩形的文本块为对象进行操作<br>
o （小）让光标置于被选中文本的对角，如果时单独一列，就是上下移动。提示: o 代表other end另一头)<br>
O （大）让光标在同一行的左右两个角之间移动<br>
p （小）把放入缓存的内容放到当前光标后面（提示：p即put）.3p,可以把三分放入当前光标后。<br>
P （大）把放入缓存的内容放到当前光标前面.<br>
y （小）把文本复制到一个寄存器中，该寄存器为vim私有的。该命令是一个操作符命令，如：&ldquo;yy&rdquo;复制一整行，&ldquo;y2w&rdquo;复制两个word，包括后面的空白字符，&ldquo;ye&rdquo;复制一个word，不包括后面的空白字符，&ldquo;y$&rdquo;复制当前光标至行尾.<br>
Y （大）复制一整行。<br>
c （小）<br>
 <br>
========================================================================================<br>
五、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  replace模式（大写的&quot;R&quot;可以进入替换模式）：<br>
replace模式下的例外是按下回车键并不会把当前字符替换为回车, 而是插入一个回车<br>
小节：<br>
x 删除当前光标下的字符(&quot;dl&quot;的快捷命令)<br>
X 删除当前光标之前的字符(&quot;dh&quot;的快捷命令)<br>
D 删除自当前光标至行尾的内容(&quot;d$&quot;的快捷命令)<br>
dw 删除自当前光标至下一个word的开头<br>
db 删除自当前光标至前一个word的开始<br>
diw 删除当前光标所在的word(不包括空白字符)<br>
daw 删除当前光标所在的word(包括空白字符)<br>
dG 删除当前行至文件尾的内容<br>
dgg 删除当前行至文件头的内容&nbsp;&nbsp;  （用&quot;c&quot;命令代替&quot;d&quot;这些命令就都变成更改命令）<br>
 <br>
~ 改变当前光标下字符的大小写, 并将光标移至下一个字符. 这不是一个操作符命令(除非你设置了°tildeop° 3选项), 所以你不能让它与一个位移命令搭配使用. 但它可以在Visual模式下改变所有被选中的文本的大小写.<br>
I 将光标置于当前行第一个非空白字符处并进入Insert模式<br>
A 当光标置于当前行尾并进入Insert模式<br>
六、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  其他东东<br>
:edit . &quot;编辑当前的目录，可用的选项有：<br>
&quot; &lt;enter&gt; : 打开一个文件或目录~<br>
&quot; o : 为文件或目录打开一个新的窗口~<br>
&quot; O : 在前一个被访问过的窗口中打开指定的文件/目录<br>
&quot; p : 预览文件/目录~<br>
&quot; i : 切换大小/日期的列表显示~<br>
&quot; s : 选择一个排序键r : 逆向排序~<br>
&quot; - : 进入父目录c : 进入目录<br>
&quot; R : 文件重命名D : 删除文件<br>
&quot; :help help-explorer得到更多信息~<br>
&lt;Enter&gt; 使用当前的窗口<br>
o 打开一个新窗口<br>
O 使用最近使用过的其它窗口[[译: 如果只有当前窗口就打开新窗口]]<br>
p 同O, 但同时还将光标定位于该窗口中<br>
参考|preview-window|<br>
i 切换显示文件的大小和日期/时间信息<br>
s 光标所在的条目作为排序键进行排序. 首先用i命令打开<br>
对文件大小和日期的显示. 然后将光标移到任一文件的大小<br>
上按下s. 此时所有的文件都将按其大小进行排序. 光标置<br>
于日期上时按s则会按其日期进行排序.<br>
r 逆向排序当前的排序列表(either size or date)<br>
c 将当前目录切换到当前光标所在的目录名. 接下来使用&quot;:edit&quot;<br>
命令时就无需附加路径名了<br>
R 更改当前光标下的文件, Vim会提示你输入一个新的文件名[[译: 不支持目录更名]].<br>
D 删除当前光标下的文件名. Vim也会提示你进行确认[[译: 不支持目录的删除]].<br>
关于编程常用快捷键：<br>
[ [ = 移动到前一个行首的'{'字符上, 等价于?^{<br>
] ] = 移动到下一个行首的'{'字符上, 等价于/^{<br>
[ ] = 移动到前一个行首的'}'字符上, 等价于?^}<br>
] [ = 移动到下一个行首的'}'字符上, 等价于?^}<br>
{ = 到前一个空行上<br>
} = 到下一个空行上<br>
gd = 到当前局部变量的定义处(当前的意思是光标停留其上的单词).<br>
* = 到与当前单词相同的下一个单词上<br>
# = 到与当前单词相同的上一个单词上<br>
'' = 到上次光标停靠的行<br>
ctags：<br>
[/home/someuser/src]$ ctags * &quot;以源程序目录下所有文件作为参数&quot;<br>
[/home/someuser/src]$ vi -t foo_bar &quot;在命令行上启动vi程序时通过-t选项加要跳转的程序元素名&quot;<br>
灾难恢复<br>
vim -r &quot;Vim会读取交换文件(这正是存放你已编辑的文件的地方)以及你的原文件的一些信息.&quot;<br>
|swap-file| &quot;关于交换文件的位置和命名&quot;<br>
|preserve| &quot;手工刷新交换文件&quot;<br>
|swapname| &quot;查看原文件及其交换文件的名字&quot;<br>
`updatecount` &quot;连续击键多少次后做一次同步&quot;<br>
`updatetime` &quot;多长时间之后做一次同步&quot;<br>
`swapsync` &quot;同步交换文件时是否同时做一次磁盘同步&quot;<br>
`directory` &quot;列出存放交换文件的目录&quot;<br>
`maxmem` &quot;尚未写入交换文件的内容所受的内存限制&quot;<br>
`maxmemtot` &quot;同上, 但是针对所有文件.&quot;<br>
========================================================================================<br>
注意&quot;o&quot;和&quot;O&quot;在Visual模式与Normal模式下行为迥异, 在Normal模<br>
式下它们是在当前行的下面或上面插入一个新行.<br>
========================================================================================注：汉字的空格不被视为空白字符<br>
要改变Vim对word边界的定义, 请查看°iskeyword°选项<br>
用％处理哪些括号可以由`matchpairs`选项来定义与滚屏相关的命令, 请参考jQ scj.若要一直保持当前行的前后都有一些内容显示在屏幕上, 请参考`scrolloff`选项.<br>
问题:在使用*键时，但如果要匹配一小片包含了几个word的文本呢?如何避免手工键入?<br>
答案: Visual select, yank, :let @/=@&quot;, n<br>
在使用:set hlsearch时，如果排除函数外别处同名变量的干扰呢? 答: j/\%&lt;3lj 限定<br>
========================================================================================添加一个plugin<br>
plugin是一个Vim会自动载入执行的脚本. 把一个脚本放入你的plugin目录即可。分为：全局的plugin，和文件类型plugin<br>
全局的plugin：<br>
在|standard-plugin-list|有一个此类plugin 的列表. 另外请参考|load-plugins|.在$VIMRUNTIME/macros下的脚本是全局的,且必需以&quot;.vim&quot;为扩展名<br>
文件类型plugin：<br>
Vim的发布版中已经包括了针对不同文件类型的相应plugin, 你可以使用&quot;:filetype plugin on&quot;命令开启对它的应用.在$VIMRUNTIME/ftplugin目录下的则是专用于特定文件类型的<br>
一些帮助：<br>
|filetype-plugins| 关于文件类型plugin的文档以及如何避免映射引起冲突的信息<br>
|load-plugins| 关于Vim启动过程中何时载入全局plugin<br>
|ftplugin-overrule| 如何强制改变全局plugin中的设置.<br>
|write-plugin| 如何写一个plugin脚本.<br>
|plugin-details| 关于如何使用plugin或者解决你的plugin出现的bug.<br>
|new-filetype| 如何检测新文件类型<br>
========================================================================================常用选项：<br>
vnoremap p &lt;Esc&gt;:let current_reg = @&quot;&lt;CR&gt;gvs&lt;C-R&gt;=current_reg&lt;CR&gt;&lt;Esc&gt; &quot;让&quot;p&quot;可以在Visual模式下以此前yank的内容替换当前选择的文本块&quot;<br>
if has(&quot;vms&quot;)<br>
set nobackup<br>
else<br>
set backup<br>
endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  在覆盖一个文件之前备份该文件. 但是对VMS系统除外, 因为该系统已经为文件保存了老的版本. 备份文件名由当前文件名<br>
加后辍&quot;~&quot;组成. 请参考|07.4|<br>
 <br>
if &amp;t_Co &gt; 2 || has(&quot;gui_running&quot;)<br>
syntax on<br>
set hlsearch<br>
endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  打开语法高亮功能, 前提是当前系统支持彩色显示. `hlsearch`告<br>
诉Vim高亮显示所有与最后一次搜索目标串相匹配的文本<br>
 <br>
autocmd BufReadPost *<br>
\ if line(&quot;°\&quot;&quot;) &gt; 0 &amp;&amp; line(&quot;°\&quot;&quot;) &lt;= line(&quot;$&quot;) |<br>
\ exe &quot;normal g`\&quot;&quot; |<br>
\ endif&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  检查是否定义了标记&quot;2, 如果定义了就跳转到这个位置去. 每一行前面的反斜杠表示该行是前一行命令的延续. 它可以避免<br>
脚本中有些行变得过长 <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/0a10cedf0574991a485403e3.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/linux%20idiot%28%C8%D5%B3%A3%29">linux idiot(日常)</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/0a10cedf0574991a485403e3.html#comment">查看评论</a>]]></description>
        <pubDate>2009-07-13  15:34</pubDate>
        <category><![CDATA[linux idiot(日常)]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/0a10cedf0574991a485403e3.html</guid>
</item>

<item>
        <title><![CDATA[ABS notes (2)]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/fd456c035cfbed81d53f7ce4.html]]></link>
        <description><![CDATA[
		
		<p>TODO: 添加12，13章未完的命令的参数 <br>
<br>
第12章 外部命令<br>
1. 基本命令:<br>
(1) ls -R 递归 -F在文件后加类型标识 -S按照文件大小排列 -t按文件修改时间排列 -i打印inode号 --time=atime/ctime，默认不写就是mtime<br>
(2)tac 和cat相反，从最后一行读取文件<br>
rev 反转每一行里的字符，但行的读取顺序还是从文件头开始，比如123变为321<br>
(3)cp -a 等于-dpR，因为一般的不加p的cp，就是read读取文件内容，然后write到目的地，这个目的文件的创建后的owner和权限等于该用户自己创建一个文件的权限。如果你想保持原有的文件owner和权限，即让ls -l显示出来的一样，就要用p，为了对目录递归和文件都有用，所以加dR，于是cp提供了-a这个简洁的参数。<br>
(4)find /dir -exec cmd {} \; 好吧，这个上面已经好多例子了，经常还用-type限制文件类型，-name限制文件名，-inum限制inode号，-mtime/-ctime/-atime限制访问时间(-mtime上次文件内容修改时间，-ctime上次inode修改时间(所有-mtime改变，-ctime跟着变)，-atime上次访问内容的时间，比如cat一个文件)。<br>
另外，可以用 -regex 来使用正则式匹配文件名<br>
(5)xargs <br>
xargs就是专门拿来构造命令的，主要采用以下两种用法：<br>
ls | xargs -n2 diff&#160; 这样的话，xargs会把标准输入，这里就是ls了，把标准输入两个两个一组，调用diff，给它两个参数。比如ls 为 a.txt b.txt c.txt d.txt的话，结果就是两次diff调用：diff a.txt b.txt; diff c.txt d.txt<br>
ls | xargs -I {} mv {} {}.old&#160; 这样的话，将当前目录下所有文件末尾加上.old。-I 的作用是引出{}，表示后面遇上{}，就把参数填入。这里没有用-n，所以，默认是传给mv一个参数。<br>
另外，其实xargs常用到find里，这时，只需要用 find ... -print|xargs ... 即可。比-exec方便。注意，-exec现在的实现，也是一个参数调用后面命令一次，并不是把所有参数堆到一起，再执行命令。且，如果用-exec来达到-I的效果，是一样的，比如 -exec mv {} {}.old<br>
(6)expr 再研究<br>
(7)date +要放在格式前，+%s表示unix秒数，+%j表示今天是今年第几天。date也可以设置时间 date -s '20060927 10:03:00'。还常用做墙上时间和绝对秒数之间的转换: date -d &quot;1970-1-1 UTC 212121221 seconds&quot; +&quot;%Y-%m-%d %T %z&quot; 就是把秒数转换为墙上时间，date -d &quot;2009-06-16 09:30:00&quot; +&quot;%s&quot; 反过来也一样。如果是绝对天数，那么把其中的seconds改为days<br>
(8)touch 还得提一下，touch改变的是mtime/ctime/atime三个时间！！它的作用是，用一个不用的文件，来keep比如某个目录最后一次xxx的时间。比如简单的记录一个项目的修改时间。<br>
(9)at 很easy的，at 时间 然后敲回车，输入你想要执行的命令，最后按ctrl-d结束。时间可以是&quot;14:30 Friday&quot; &quot;23:20 today&quot; 形式等。也可以用-f指定命令文件。<br>
(10)cal 日历<br>
(11)sleep 可以以分，小时，天为单位：sleep 3 h 睡3小时<br>
(12)usleep micro second的sleep<br>
<br>
2. 文本处理<br>
先来看个经典例子：<br>
cat $* |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Contents of specified files to stdout.<br>
tr A&#8722;Z a&#8722;z |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Convert to lowercase.<br>
tr ' ' '\012' |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # New: change spaces to newlines.<br>
#tr &#8722;cd '\012[a&#8722;z][0&#8722;9]' |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Get rid of everything non&#8722;alphanumeric<br>
#+ (original script).<br>
tr &#8722;c '\012a&#8722;z'&#160;&#160;  '\012' |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Rather than deleting<br>
#+ now change non&#8722;alpha to newlines.<br>
sort |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # $SORT options unnecessary now.<br>
uniq |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Remove duplicates.<br>
grep &#8722;v '^#' |&#160;&#160;&#160;&#160;&#160;&#160;  # Delete lines beginning with a hashmark.<br>
grep &#8722;v '^$'&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Delete blank lines.<br>
再看一个经典的变形：<br>
cat hehe.txt |tr ' ' '\n'|grep -v '^$'|sort|uniq -c|sort -nr<br>
尤其是后面的 sort|uniq -c|sort -nr 是很常用的组合。-n是书上加的，不知道只写-r有什么不妥。<br>
<br>
(1)sort -r 反向 -m 将两个已经排好序的文件合并成排序的文件<br>
(2)uniq 去掉相邻的重复项, -c在行首打印重复次数<br>
(3)expand,unexpand 把tab转换为空格，和相反转化<br>
(4)cut 就是awk '{print $n}'的简化版。 cut -d ':' -f1,2,3 表示打印1,2,3列，分割符是:. 还有个有用的是 -c1-10 表示只打印每一行的1到10个字符，这可以用于提取连续字段中某一段。<br>
(5)paste: 将文件2接到文件1中，接的方法有两个，默认是把2中的每行接在1中的每行后。如果用-s，则是将文件1的所有行以tab隔开，做为一个新行，将文件2的所有行也做为一个新行，结果就是两行。用-d可以指定分割符。paste也经常和cut用于log系统。<br>
(6)join: 被认为是paste的堂兄，它做的事情有时更有意义: 大循环是遍历文件1中的行，小循环是对文件1中的某行，来遍历文件2中的所有行。当文件2中的行的第一个字段和文件1中的行的第一个字段相同时，把它接在文件1中的行后，但是去掉第一个字段，也就是新行只有一个“第一个字段”。多用于两个文件，有相同的关键字的行的整合。类似数据库操作。<br>
(7)head: -c2 打印文件前面2个字符 -n 打印文件前面n行<br>
(8)tail: 和head完全相同。注意有个-f参数很有用 tail -f /logfile 如果logfile被append了，它就会输出被append的东西。我用&gt;&gt;来append是有用的，但是用vim来append是没有用的。<br>
(9)grep: -i 忽略大小写 -l 打印匹配的文件而不是行 -r 递归 -n 附带打印行号 -v 过滤掉某行 -c 打印匹配数 ———— 还是尽量用egrep吧，它等于grep -E，它支持多一些正则式，比grep好用些。另外，如果要搜索.gz压缩文件，还是用z打头的，如zgrep,zegrep吧。比如一个文件夹下面普通文件和压缩文件都有，那么用zgrep,zegrep更方便些。如果是.bz2文件，用bz打头的，如bzgrep,bzegrep。<br>
另外，grep常用做条件测试，判断一个字符串是否满足要求，因为如果匹配，它返回0。<br>
(10)look: 就是简单的grep, look string file 是返回以string开头的file的行。所以它是为字典查找设计的，就是看行首的字节。<br>
(11)wc: wc有个很大的好处，可以得到多个文件的总字节数. wc [d-h]* | grep total | awk '{print $3}'就可以了。其他重要的，-w单词数 -l 行数 -c字节数 -L最长行的长度，这些可以计算一个命令的输出内容。<br>
(12)tr: 它需要用&lt;filename来操作文件。除了常用的两参数模式，如tr &quot;A-Z&quot; &quot;a-z&quot;&lt;filename把大写转换为小写外，还有其他有用选项。-d &quot;0-9&quot; 单参数，去掉文件中的数字，-s 'x' 去掉连续的x，但保留第一个，比如用于去掉多余空格。-c取反，tr -c &quot;b-d&quot; &quot;+&quot; 表示不是b-d的才替代为+。 好吧，tr 'a&#8722;zA&#8722;Z' 'n&#8722;za&#8722;mN&#8722;ZA&#8722;M'，居然也可以，就是把任意一个序列转换为任意对应的字符。<br>
(13)fold: 用于断行，-s 断行，但是只在发现空格的地方。-w限制一行长度，是硬断行<br>
(14)fmt: 也用于断行，这个比fold好用一点，直接 fmt -w 2 表示如果该行的长度大于2，那么遇到空格就得换行。这个很人性化。<br>
(15)col: 暂不研究<br>
(16)column: 这个就很有用了，制作漂亮对齐的表格。比如你想给表格加个头，想让头和内容能对齐:<br>
(printf &quot;PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG&#8722;NAME\n&quot; \ ; ls -l | sed 1d) | column -t <br>
这里printf和ls的输出，要一起经过column处理，所以用()启动一个子shell，之后column 的-t会把每一列对齐！！ -t就是制作table的意思，是最常用的。 <br>
(17)colrm: 删除指定的列——这个列指字符，不是靠空格等分割的列。colrm 2 4 &lt; filename 表示删除2到4列，其他的输出到屏幕<br>
(18)nl: cat -n是给每一行加上行号，nl是给每一个非空行加上行号，但是空行也会打印<br>
(19)pr: 能够将较大的文件分割成多个页面，并为每个页面添加标题。主要用于得到适合打印的文本。功能很强大，是nl, paste, fold, column, expand的超集。<br>
(20)gettext: 暂不研究，和localization相关<br>
(21)msgfmt: 赞不研究，和localization相关<br>
(22)iconv: 修改文件内容编码 iconv -f gbk -t utf8 a.html -o b.html 它的兄弟命令是convmv，修改文件名编码， convmv -f gb2312 -t utf8 -r --notest *（如果不加notest，则不会做实际转换）<br>
<br>
3. 文件和打包：<br>
------------ 打包 -------------<br>
(1)tar<br>
(2)ar rcs<br>
(3)rpm<br>
(4)cpio,rpm2cpio<br>
(5)gzip,bzip2: -d表示解压。我想说，没有找到直接压缩多个文件的做法，只能先用 tar打包后再压缩。所以，如果是多个文件用tar打包的话，你用zcat,bzcat打印出的东西，除了每个文件的内容外，还会含有tar维护的信息，如owner，权限... zcat,bzcat等于 -dc<br>
(6)zip,unzip: 这两个，其实是tar和gzip的结合，即可以压缩多个文件。它也是Internet上常见的那种zip。<br>
<br>
------------ 文件信息 -----------<br>
(1)file: 比如告诉你ASCII text，或者UTF-8 Unicode text<br>
(2)which: 可执行文件的路径<br>
(3)whereis: 居然可以找各种文件...包括资源文件和man文件<br>
(4)readlink: 和ls -l最后一列信息相同<br>
(5)strings: 提取一个二进制文件中的printable信息，比如能让你容易判断一个文件类型，比如一个图片里有JFIF，则多半是一个JPEF文件。<br>
<br>
------------ 比较 -----------<br>
(1)diff,patch</p>
<p>&lt;&lt; 基本用法 &gt;&gt;<br>
生成和打补丁：(记忆方式和cp,ln类似，从dir生成dir2，需要名为dir1-to-dir2.patch的补丁文件)<br>
diff -uNr dir1 dir2 &gt; dir1-to-dir2.patch  # 对目录下所有文件生成补丁<br>
patch -p0 &lt; dir1-to-dir2.patch # patch时在dir1,dir2所在目录下<br>
patch -p1 &lt; ../dir1-to-dir2.patch # patch时在dir1所在目录下(p0和p1就这区别)<br>
patch -p1 -R &lt; ../dir1-to-dir2.patch # patch时在dir1所在目录下(p0和p1就这区别)，将变为file2的file1，再变回来</p>
<p>diff -uN file1 file2 &gt; file1-to-file2.patch # 对文件打补丁<br>
patch -p0 &lt; dir1-to-dir2.patch # patch时在dir1,dir2所在目录下<br>
patch -p0 -R &lt; dir1-to-dir2.patch # patch时在dir1,dir2所在目录下，将变为file2的file1，再变回来</p>
<p>说明：<br>
其中 -u 表示生成补丁文件的格式，那个文件格式很好懂得，-表示准备去掉的行，+表示准备加上的行，其实就说明了两个文件间的差异。它和vimdiff不一样，vimdiff是在两个窗口中对比那一行，而diff的-u输出是patch文件中用-和+，上下来看。而且用diff比vim的好处是，可以一次性递归列出所有文件的所有要改的地方。其实在比如codereview的时候，很方便。-r表示递归。-N加上把，不太懂。patch时候，-R表示把变为file2的file1再变回来。<br>
另外，patch时候，加个--dry-run的话，就能够只显示将要patch的文件，而不会真正patch.<br>
&lt;&lt; 只用diff找出两个文件夹下独有的文件名 &gt;&gt;<br>
diff -r dir1 dir2 |grep Only<br>
&lt;&lt; 只用diff找出两个文件夹下独有的文件名，和内容不同的文件 &gt;&gt;<br>
diff -rq dir1 dir2&#160;&#160;  # -q 只说明两个文件不同，不显示差异</p>
<p><br>
(2)cmp: 简单diff，只显示第一处不同的地方<br>
(3)comm: 打印三列: 文件1独有的，文件2独有的，两文件共有的行<br>
<br>
------------ 小工具 ------------<br>
(1)basename &amp; dirname：将文件名和路径名从全路径中抽取出来。<br>
(2)split: 用于分割大文件<br>
(3)md5sum<br>
(4)shred: 用于乱涂一个文件。即你想删除一个文件，但是如果直接用rm来删，会使得别人容易从硬盘恢复，所以先用shred搞乱。<br>
(5)mktemp: 用于在某目录下生成唯一的文件，mktemp /tmp/hah.XXXXXX 注意，XXXXXX你可以随便添加多少个X，它会被mktemp转换为唯一的字符串<br>
<br>
------------ 编码 -------------<br>
(1)uuencode,uudecode: 在二进制和ASCII码间相互转换<br>
(2)mimencode,mmencode: 同上，针对的是多媒体文件<br>
<br>
4. 通信工具<br>
(1)host,dig 从DNS服务器获取信息，典型的如DNS查找(域名-&gt;IP)和反向查找(IP-&gt;域名)等功能。<br>
比如反向：<br>
dig www.google.com 你会看见google的ip地址, dig -x googleip地址 你会看见google域名，在最后，你会看到SERVER就是你本次查询的服务器。<br>
(nslookup已经过时了，因为它没有dig灵活)<br>
(2)... 好多命令，以后研究<br>
<br>
5. 终端控制命令<br>
(1)... 好多命令，以后研究<br>
<br>
6. 数学命令<br>
(1)... 好多命令，以后研究<br>
<br>
7. 更多命令<br>
(1)jot,seq<br>
(2)...<br>
<br>
<br>
第13章 系统管理命令<br>
---------- 用户和组 ------------<br>
(1)groups: 后跟用户名，列出用户所属的所有组<br>
(2)chown,chgrp: 改变文件的用户或组<br>
(3)id: 后跟用户名，列出用户的uid，gid，所属组等信息<br>
(4)who: 打印所有终端上目前的登录信息<br>
(5)w: 等于who加终端上跑的进程，包括tty的和pts的<br>
(6)logname: 当你su后，whoami显示是root，但是logname还是你自己<br>
(7)last: 显示登录过的用户，最近登录的排在最前面，包括当前还活跃的。<br>
(8)gpasswd: gpasswd -a &lt;user&gt; &lt;group_name&gt;为组添加用户，换为-d就是从组里删除用户<br>
(9)useradd,userdel,groupadd,groupdel 参数比较easy<br>
(10)pgrep,pkill:&#160; pgrep -u fengyi -t pts/1 可以找出fengyi用户在终端pts/1上的所有进程！！ 输出是纯粹的pid号，如果你加-l，就一块列出进程名。如果参数中你给了进程名，就只列出那个进程的pid，但是如果你加了-u和-t指定用户名和终端，则可能找不到匹配的呵呵。 注意，-u后面跟的是effective uid，如果要跟real uid，用-U。 另外，pkill和pgrep参数一样，不同的是，它不是列出那些进程号，而是给那些进程发送你规定的信号！！ 这个可方便了，比如杀死所有的某种进程。</p>
<p>---------- 终端相关 ------------<br>
(1)wall: 向所有终端发信息<br>
(2)dmesg: 打印系统启动的信息<br>
(3)好多，暂时不研究<br>
---------- 信息和统计 -----------<br>
(1)lsof: 列出opened files，以及打开它的命令，用户等信息<br>
(2)strace: 后接可执行文件名，列出该命令的含有的系统调用。<br>
(3)free: 列出memory,cache和swap的信息<br>
(4)stat: 列出一个文件的n多信息，相当于ls能得到的所有信息的汇总<br>
(5)vmstat: 列出虚拟内存的信息<br>
(6)uptime: 列出系统从启动为止到现在的时间<br>
(7)readelf,ldd：读取二进制文件信息 <br>
(8)好多，暂时不研究<br>
----------- 系统日志 ------------<br>
(1)logger: 就是syslog的命令版。注意要指定facility和priority<br>
(2)<br>
----------- 任务管理 ------------<br>
(1)pidof: pidof接程序名，列出所有运行它的进程PID。<br>
(2)<br>
----------- 系统控制和启动 ----------<br>
(1)init... 暂时不研究<br>
------------ 网络 ---------------<br>
------------ 文件系统 -------------<br>
----------- 备份 -------------<br>
----------- 系统资源 ----------<br>
----------- 模块 ------------<br>
----------- 其他 ------------<br>
<br>
at命令用法：“at -f shell文件 时间” 就会在时间执行shell文件。如果不用 -f 引出文件，那么就 “at 时间”，然后at会提示你输入命令，每一行输入你想执行的命令即可。完了，按Ctl-D输入结束。用 atq 可以查看等待执行的任务。用atrm可以删除某一任务。 比较郁闷的是，在ubuntu9.04上，只有一些命令可以被at执行，比如touch，但是mplayer却不行？ 但是在ubuntu8.10上，什么命令都可以跑。另外注意，at有配置文件在 /etc/at.allow 和 /etc/at.deny，一般不用管，但是需要控制用户使用at的权限时，就要用了。<br>
<br>
<br>
<br>
<br>
<br>
第14章 命令替代<br>
这一章意思就是，一个变量值，可以用``或$()来从命令获取。这里唯一值得提的是：while for if等同样是命令，里面需要含有echo语句，如下：<br>
variable1=`for i in 1 2 3 4 5<br>
do<br>
echo &#8722;n &quot;$i&quot;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # The 'echo' command is critical<br>
done`&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  #+ to command substitution.<br>
echo &quot;variable1 = $variable1&quot; # variable1 = 12345<br>
<br>
<br>
第15章 算术运算<br>
在前面已经说了，这里重复一下，有三种，$(())，let 和 expr。其中$(())以前我爱用，let用得少，但确实好用，expr用的少。<br>
<br>
第16章 I/O重定向<br>
这一章已经比较熟了，只有一些要说明如下：<br>
&amp;&gt;filename 表示重定向0和1两个都到filename.<br>
<br>
打开文件，读写导致位置移动！！！虽然没有seek，tell<br>
echo 1234567890 &gt; File # Write string to &quot;File&quot;.<br>
exec 3&lt;&gt; File&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Open &quot;File&quot; and assign fd 3 to it.<br>
read &#8722;n 4 &lt;&amp;3&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Read only 4 characters.<br>
echo &#8722;n . &gt;&amp;3&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Write a decimal point there.<br>
exec 3&gt;&amp;&#8722;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # Close fd 3.<br>
cat File&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  # ==&gt; 1234.67890<br>
说明：这里的两个exec是用于打开和关闭文件，相当于open和close，打开时为之赋予你需要的描述符，这里是3，关闭时也是关闭3。里面的read会导致游标移动，使得echo（想当于write）写出的位置发生变化。（这里的两个exec不会导致shell被替换掉，无语）。更多的关于关闭文件描述符的介绍，见P251。<br>
<br>
多个重定向的书写顺序：<br>
ls -z 2&gt;&amp;1 &gt;&gt;cow.txt 这个试图把-z这个错误选项的错误信息输出到cow.txt，但是不成功，还是打印到了终端上，这是因为，这里的逻辑是：被依赖的写前面。显然，这里是2&gt;1&gt;cow.txt，这里有两个管道，一是2&gt;1，二是1&gt;cow.txt，前者依赖于后者，所以，需要你把后者写前面。这样就对了：ls -z &gt;&gt;cow.txt 2&gt;&amp;1<br>
<br>
exec的作用：<br>
(1)打开和关闭文件：上面已经说了<br>
(2)重定向本shell中的描述符：典型应用是，不必要为每个read或其他从stdin输入的命令都做重定向到文件，而是在前面用一次exec即可。这样方便对文件的处理。对于echo等输出命令，也是同理的。比如对read来说，可以这样：<br>
exec 6&lt;&amp;0&#160;&#160;&#160;&#160;&#160;&#160;&#160;  #dup 0 到6，6用做0的临时存储地<br>
exec &lt; data-file #重定向0到文件<br>
...&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  #各种read或其他命令来处理文件，典型的用法是不断read，来提取文件每一行，然后用sed/awk处理。但这里其实我们在上面的while循环中已经做了对while的重定向了，即在while/for/until/if等的最后（比如done后）加个&lt; filename 即可以达到类似的目的，已经可以达到取出每一行，然后来处理。（插一句，函数居然也可以被重定向！可能因为他们都是代码块的缘故）<br>
exec 0&lt;&amp;6 6&lt;&amp;&#8722;&#160;&#160;  #把6 dup回来到0，并关闭6<br>
(3)代替本shell，执行一个命令，就是一般用法。<br>
<br>
<br>
第17章 here文档<br>
here文档，就是型如下面的文档：<br>
#!/bin/bash<br>
interactive&#8722;program &lt;&lt;LimitString<br>
command #1<br>
command #2<br>
...<br>
LimitString<br>
<br>
作用是将一系列命令喂给interactive-program。这行为是shell的行为，即如果你写interactive-program &lt; limitString，shell会以为你的输入来自limitString文件，但是如果你写 &lt;&lt; limitString，shell就会以为你要开始喂命令了，并将limitString理解为命令的结束标志，这样，你就可以不断写命令了，一行一行的，直到你写了limitString敲个回车，这时，shell才把你的命令给interactive-program，当然你写的有空格就有空格，每一行都有换行，把这整体给program.然后就看program怎么理解这些输入了，一般的program是一次读一行型的，所以正好可以！（这里“命令”的意思，不一定是命令，也可能是一般的输入等待处理，比如你用 cat &lt;&lt; cow 试试）<br>
<br>
典型例子：登录ftp服务器，并打印目录信息：注意用到变量:<br>
cmd=ls<br>
ftp -n openware.byr.edu.cn &lt;&lt; endofcmd<br>
user anonymous anonymous<br>
$cmd<br>
bye<br>
endofcmd<br>
但是，如果endofcmd被加了引号，那么里面的所有的特殊字符都无效了。<br>
cmd=ls<br>
ftp -n openware.byr.edu.cn &lt;&lt; 'endofcmd'<br>
user anonymous anonymous<br>
$cmd&#160;&#160;&#160;&#160;  #这里实际是无效的，ftp服务器会收到&quot;$cmd&quot;而已，而不是ls<br>
bye<br>
endofcmd<br>
<br>
函数也被当成上面的interactive-program一样来用！！！<br>
<br>
最后，作者提到，对于太复杂的东西，还是用expect来做更easy。<br>
其实以前我是用管道来做的，效果一样。管道的左边是一个函数或者shell脚本即可，右边是ftp等交互式命令。<br>
<br>
第18章 纯属搞笑<br>
<br>
<br>
<br>
<br>
五、高级主题<br>
第19章 正则表达式<br>
1. 正则式RegularExpressions(RE)：<br>
用于sed，awk，egrep(好多对于grep不适用)，其实挺简单，记住如下这些即可应付大多数场合，要提醒的是，以下以awk为准，其中有些元字符在sed，egrep中要用的话，得加\来转义，如+<br>
<br>
把\D加进去，看看上次百度笔试后晚上下的文档，补充一下！！！！！！！！！！！！！！！！！！！！！！！！<br>
<br>
<br>
(1) 基本RE：<br>
.任何一个字符，除了newline<br>
*和前面的连用，表示出现0次或多次<br>
^$匹配空白行<br>
[xyz]&#160;&#160;&#160;  匹配x,y或者z<br>
[c-n]&#160;&#160;&#160;  匹配c-n范围内的所有字符<br>
[B-Pk-y] 匹配B-P和k-y范围内的所有字符<br>
[a-z0-9] 匹配小写字符或者数字<br>
[^b-d]&#160;&#160;  匹配b-d范围以外的字符<br>
\&lt;the\&gt; 匹配the单个单词，不包括them之类的<br>
(2) 扩展RE：<br>
?和前面的连用，表示出现0次或1次<br>
+和前面的连用，表示出现1次或多次<br>
\{5\}和前面的连用，表示出现5次<br>
(re1|re2|re3)表示或者是re1，或者是re2，或者是re3，即()里写正则式组<br>
(3) POSIX RE:<br>
[:alnum:] This is equivalent to [A&#8722;Za&#8722;z0&#8722;9].<br>
[:alpha:] This is equivalent to [A&#8722;Za&#8722;z].<br>
[:blank:] matches a space or a tab.<br>
[:cntrl:] matches control characters.<br>
[:digit:] matches (decimal) digits. This is equivalent to [0&#8722;9].<br>
[:graph:] (graphic printable characters). Matches characters in the range of ASCII 33 &#8722; 126. This is the same as [:print:], below, but excluding the space character.<br>
[:print:] (printable characters). Matches characters in the range of ASCII 32 &#8722; 126. This is the same as [:graph:], above, but adding the space character.<br>
[:space:] matches whitespace characters (space and horizontal tab).<br>
[:lower:] This is equivalent to [a&#8722;z].<br>
[:upper:] This is equivalent to [A&#8722;Z].<br>
[:xdigit:] matches hexadecimal digits. This is equivalent to [0&#8722;9A&#8722;Fa&#8722;f].<br>
不过，使用的时候，要再加个[]，如grep [[:digit:]] test.file<br>
<br>
2. globbing：shell不理解正则式，它只是做通配符的扩展<br>
通配符如下：<br>
*0个或多个任意字符。<br>
?1个任意字符，提醒的是*和?不再和前面的连用，而是单独使用。<br>
[^abc]用法同正则式<br>
{通配符1,通配符2,通配符3} 这等于RE中的() 注意，这里,两边没有空格，且至少要放入两个通配符，或者{通配符1,}式，即有,号<br>
如：ls -l|egrep '(cow\.|hehe\.)' 等于 ls -l {cow.*,hehe.*}<br>
<br>
shell的有两个要点提示如下：<br>
(1)匹配什么就要写全，比如c，只能匹配到c，而 c*，匹配不到 bc，这点和RE不一样，RE只需要含有要匹配的字符串的一部分即可。<br>
(2)单独的*不能匹配以.开头的文件。除了借助egrep，sed，awk来找外，可以这样：<br>
ls {.[^.]*,..?*} 这表示匹配.abc，或者..dd之类的文件。<br>
<br>
<br>
第20章 子shell<br>
在上面介绍wait的时候，已经写了用子shell来做并行计算了。这里清晰一个概念：<br>
用()括起来的子shell执行码，如果不加&amp;的话，和普通执行的区别是：原shell会启动一个子shell来执行这段代码，所以你可以随意改东西，比如环境变量等！！注意的是，同启动一个子进行来执行命令一样，原shell会等待子shell结束后再执行。所以，你要并行计算的话，就加&amp;吧。<br>
<br>
第21章 限制的shell<br>
当你用set -r时，就把shell置于了restricted状态，在这个状态下，一些命令如cd，一些操作，如重定向是不起作用的，具体不起作用的东西见P279列出的。<br>
目的是防止可能的damage to system<br>
<br>
第22章 进程替代<br>
就和命令替代一样，意思是将进程的输出赋值给一个变量，语法上见P281<br>
<br>
第23章 函数<br>
下面第一个最常用：<br>
function_name () {<br>
command...<br>
return(可选，如果不写，返回的就是最后一个命令的退出码)<br>
}<br>
或者<br>
function_name () <br>
{<br>
command...<br>
return<br>
}<br>
或者<br>
function function_name {<br>
command...<br>
return<br>
}<br>
<br>
然后用名字直接调用即可，如 function_name arg1 arg2<br>
参数的话，在函数里用$1,$2来引用即可，()里不需要写什么<br>
另外，为了得到返回的东西（不是函数return的），方法是在函数里直接写变量，这个变量默认就是全局的，然后在函数外面直接得到之即可。<br>
<br>
但是，局部的变量呢，必须要用local声明，如local var=20。局部变量的好处是，使得递归成为可能。<br>
<br>
另外，注意，函数这种代码块，也可以用管道和&lt;，&gt;来操作。<br>
<br>
<br>
第24章 Aliases<br>
easy阿<br>
<br>
第25章 List Constructs<br>
这一章讲的是用 cmd1 &amp;&amp; cmd2 &amp;&amp; cmd3 ... 和 cmd1 || cmd2 || cmd3 ... 来替代if/then, case之类的。简单的还可以用这个，复杂的真不好看。<br>
规则是:<br>
cmd1如果为假，就不会走 cmd1 &amp;&amp; cmd2 &amp;&amp; cmd3 中的cmd2和cmd3<br>
cmd1如果为真，就不会走 cmd1 || cmd2 || cmd3 中的cmd2和cmd3<br>
<br>
第26章 数组<br>
还是别看了，太多了，见前面提到的基本的即可。<br>
注意的是，为了实现一些本该用C实现的算法，在shell里用数组往往更容易。<br>
<br>
第27章 基本文件<br>
1. startup file<br>
/etc/profile&#160;&#160;&#160;&#160;&#160;&#160;&#160;  Bourne模式的shell，如bash的设置文件<br>
/etc/bashrc&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;  Bash的设置文件<br>
$HOME/.bash_profile 是/etc/profile的本地版<br>
$HOME/.bashrc&#160;&#160;&#160;&#160;&#160;&#160;  是/etc/bashrc的本地版<br>
上面，只有/etc/profile 是在非login shell（如gnome-terminal）中无效的。其他的在login shell和非login shell中都有效。<br>
2. logout file<br>
$HOME/.bash_logout 用户从login shell退出的时候被执行 <br>
<br>
第28章 /dev和/proc<br>
这一章也就是大概提了下：<br>
1. /dev<br>
/dev/loop0 称为loopback设备，以前曾经把一个文件，mount到/tmp下，就是先在文件中创建文件系统，再借助/dev/loop0，具体查阅以前文档。<br>
/dev/null, /dev/zero,具体见29章. /dev/urandom 上面已经介绍了。<br>
<br>
2. /proc<br>
(1) 一大堆文件<br>
cat /proc/devices<br>
cat /proc/interrupts<br>
cat /proc/partitions<br>
cat /proc/loadavg<br>
cat /proc/filesystems<br>
cat /proc/version<br>
cat /proc/cpuinfo<br>
(2) 进程特定文件夹<br>
在proc下有许多数字文件夹，每个文件夹都是一个进程PID。<br>
里面有这个进程的信息文件，主要感兴趣的文件有下面四个：<br>
stat/status 含有进程的统计信息，用数字表示，但是这每个数字的意思我还不清楚<br>
cmdline 含有这个进程被invoke时给的参数<br>
exe&#160;&#160;&#160;&#160;  这是一个指向执行文件的链接，用ls -l可得知可执行文件的位置。<br>
<br>
书上给了两个例子，一是通过进程号查找进程的启动程序的目录，通过/proc/pid/exe，很easy。另一个是通过进程名，先用ps ax得到进程号，然后再同样查找/proc。<br>
<br>
<br>
第29章 /dev/null 和 /dev/zero<br>
/dev/null 这个就是黑洞，写了就被丢弃，读是读不出来的。所以，除了常见的重定向外，其实还可以把它链接到任何你不想存的文件。比如一个程序喜欢把你认为无用的东西写到一个文件，导致占用空间，那你可以把这个文件删掉，再链接/dev/null到这个文件。<br>
<br>
/dev/zero 用于初始化文件为全0（数字0），包括初始化设备。典型的应用是初始化一个swap文件为全0。然后swap才能被swapon。典型的是用 dd if=/dev/zero of=... 来从/dev/zero中取出你需要个数的0。<br>
<br>
<br>
第30章 Debugging<br>
好吧，不看了... 不过这一章介绍了trap的用法。<br>
<br>
第31章 bash Options<br>
这一章 介绍了通过set设置的bash选项，以及如果影响脚本。<br>
<br>
第32章 Gotchas<br>
把保留字赋给变量，比如把case这个赋给变量？？不看了...<br>
<br>
第33章 脚本风格<br>
打点...<br>
<br>
第34章 Miscellany<br>
各种小主题...<br>
<br>
第35章 Bash,version 2<br>
介绍了version 2特性<br>
<br>
第36章 Endnotes<br>
over...</p> <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/fd456c035cfbed81d53f7ce4.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/fd456c035cfbed81d53f7ce4.html#comment">查看评论</a>]]></description>
        <pubDate>2009-07-05  10:19</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/fd456c035cfbed81d53f7ce4.html</guid>
</item>

<item>
        <title><![CDATA[ABS notes (1)]]></title>
        <link><![CDATA[http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/7c1f49332328ea4aac4b5f1b.html]]></link>
        <description><![CDATA[
		
		TODO: 添加12，13章未完的命令的参数<br>
<br>
一、重用的模块：<br>
清空或创建文件：<br>
cat /dev/null &gt; /var/log/message <br>
:&gt; /var/log/message<br>
&gt; /var/log/message<br>
<br>
当前用户ID：<br>
$UID<br>
<br>
退出码归操作方法：<br>
E_XCD=66&#160;&#160;&#160;&#160;&#160;&#160;   cd不进去<br>
E_NOTROOT=67&#160;&#160;   不是root<br>
使用时： exit $E_XCD 即可，正常时 exit 0<br>
<br>
查看用户是否为root：<br>
ROOT_UID=0<br>
if [ &quot;$UID&quot; -ne &quot;$ROOT_UID&quot; ];then<br>
echo &quot;Must be root&quot;<br>
exit $E_NOTROOT<br>
fi<br>
<br>
判断参数个数是否足够：<br>
E_WRONGARGS=65<br>
if [ $# -ne 期望的个数 ];then<br>
echo &quot;Usage: ...&quot;<br>
exit $E_WRONGARGS<br>
fi<br>
<br>
<br>
参数检查，给予默认值：<br>
(1)方法一（简单）<br>
LINES=10<br>
if [ -n &quot;$1&quot; ];then #不为空，或者换为-z表示为空，但是用-z一般是用于如果没有参数，就退出的情况更方便些。<br>
lines=$1<br>
else<br>
lines=$LINES&#160;&#160;&#160;   #为空，给予默认值<br>
fi<br>
(2)方法二（高效）<br>
E_WRONGARGS=65<br>
case &quot;$1&quot; in<br>
&quot;&quot;)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   lines=50;;&#160;&#160;&#160;   #为空，给予默认值<br>
*[!0-9]*)&#160;&#160;   echo &quot;Usage:...&quot;; exit $E_WRONGARGS;; #写各种case判断错误情况，并给出回应<br>
*)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   lines=$1;;&#160;&#160;&#160;   #正确，用$1赋值<br>
esac<br>
(3)方法三（更高效）<br>
lines=${1:-50} 如果没有$1，就给50默认值，注意前面有个dash(-)<br>
<br>
<br>
判断是否进入了某个目录：<br>
(1)方法一（简单）<br>
cd $LOG_DIR<br>
if [ `pwd` != &quot;$LOG_DIR&quot; ];then<br>
echo &quot;Can't change to $LOG_DIR&quot;<br>
exit $E_XCD<br>
fi<br>
(2)方法二（高效）<br>
cd $LOG_DIR || {<br>
echo &quot;Can't change to $LOG_DIR&quot;<br>
exit $E_XCD<br>
}<br>
<br>
保留日志的最新几行：<br>
假设cd /var/log/成功<br>
tail -$lines messages &gt; mesg.tmp<br>
mv mesg.tmp &gt; messages<br>
<br>
sort和uniq：<br>
cat *.lst|sort|uniq<br>
<br>
将file的小写改为大写：<br>
tr 'a-z' 'A-Z' &lt; file<br>
<br>
看哪个文件更老：<br>
if [ $file1 -ot $file2 ];then<br>
echo &quot;file1 is older than file2&quot;<br>
fi<br>
<br>
将过去24小时内修改过的文件做备份：<br>
(1)GNU find快速版本：<br>
find . &#8722;mtime &#8722;1 &#8722;type f &#8722;print0 | xargs &#8722;0 tar rvf &quot;$archive.tar&quot;<br>
(2)Unix通用find慢速版本：<br>
find . &#8722;mtime &#8722;1 &#8722;type f &#8722;exec tar rvf &quot;$archive.tar&quot; '{}' \;<br>
注意两点：<br>
一是 -mtime +n 表示 n＊24小时前，-n表示n*24小时内，但都是现在时间以前！<br>
二是 tar 的参数，要是rvf了，不是cvf，因为find是每找到一次，就执行一次tar，所以要用r表示append文件到已有的tar中。而用cvf的话，每次都会重新刷掉以前所有的。<br>
<br>
做运算：<br>
(1)复杂写法：<br>
var=$(((1+2)*(1+2)))<br>
(2)简单写法——和书写相同<br>
let &quot;var=(1+2)*(1+2)&quot;<br>
<br>
eval：形成命令，再执行之！<br>
eval &quot;`seq 10000 | sed -e 's/.*/export var&amp;=ZZZZZZZZZZZZZZ/'`&quot;<br>
解释：先形成10000个export，再执行之。这里，seq的作用是控制export次数。<br>
注意后面有个 &amp; 这个是sed的非常有用的东西，等于前面匹配好的字串，<br>
比如 echo &quot;abc 123 bcd&quot; | sed -e 's/[0-9]\{3\}/dd';&#160; 结果是 abc dd bcd<br>
<br>
<br>
取出最后一个参数：<br>
(1) 使用eval:<br>
eval echo '${'$#'}'<br>
(2) 使用!：<br>
args=$#<br>
echo ${!args}  #不过真的没看懂，比如这里直接用 ${!$#}就不行<br>
<br>
<br>
shift参数：每shift一次，参数就往左边挪动一次，这样一直读$1就可以读到所有参数，shift也可以作用于函数参数<br>
until [ -z &quot;$1&quot; ]<br>
do<br>
echo -n &quot;$1 &quot;<br>
shift<br>
done<br>
<br>
<br>
省略if的做法： ———— 效果，使得语句很简练！ 一行搞定！！<br>
[ &quot;$var1&quot; &#8722;ne &quot;$var2&quot; ] &amp;&amp; echo &quot;$var1 is not equal to $var2&quot;<br>
[ &#8722;d &quot;$home&quot; ] || echo &quot;$home directory does not exist.&quot;<br>
<br>
<br>
P71给了一个限时输入的例子<br>
版本1，用的是trap捕获kill信号来打断正在执行的read<br>
版本2，用的是stty的设置<br>
版本3，搞笑，发现read本身提供了-t设置timeout<br>
<br>
用shell来处理一个文件的每一行：<br>
count=0<br>
while read line<br>
do<br>
let &quot;count+=1&quot;<br>
echo $count $line<br>
done &lt; /etc/passwd<br>
<br>
用shell来处理每一行的每一个字段：（用IFS在while中设置临时输入分割符）<br>
count=0<br>
while IFS=: read name passwd uid gid fullname ignore<br>
do<br>
let &quot;count+=1&quot;<br>
echo $count $name $passwd $uid $gid $fullname $ignore<br>
done &lt; /etc/passwd<br>
<br>
其实，while循环，也接受管道导入的数据：<br>
cat /etc/passwd |<br>
while read line<br>
do<br>
let &quot;count+=1&quot;<br>
echo $count $line<br>
done<br>
<br>
得到一个进程名对应的进程号：<br>
ps ax | grep -v &quot;ps ax&quot; | grep -v grep | grep $PROCNAME | awk '{ print $1 }'<br>
<br>
<br>
二、命令<br>
id -nu 得到当前用户的名字（与euid对应的）<br>
id 得到你参加的所有组名和id<br>
<br>
<br>
<br>
三、基础：<br>
第1,2章 木有<br>
<br>
<br>
第3章 特殊字符<br>
#的两个特例：<br>
echo ${PATH#*:} 参数替换（没看懂）<br>
echo $(( 2#101011 )) 基本转换（没看懂）<br>
<br>
case语句后面要加两个;;<br>
case &quot;$var&quot; in<br>
shell匹配式)  echo &quot;...&quot;;;<br>
*)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   echo &quot;...&quot;;;<br>
esac<br>
<br>
true和:只不过是两个命令<br>
前者是系统命令，后者是bash内置命令，更高效，但是不能跨平台<br>
true<br>
echo $?<br>
:<br>
echo $?<br>
<br>
:的妙用：<br>
1. 可做占位符<br>
(1) 用在if里：<br>
if condition then :<br>
else<br>
take-some-action<br>
fi<br>
(2) 用在二元运算符：<br>
: ${username=`whoami`}<br>
如果不要 :，则会包错，除非username刚好是一个命令。因为这里就是替换username的实际东西放在这里，然后执行（但我还不知道这个有什么用）<br>
2. 可做查看是否变量为空<br>
: ${HOSTNAME?} ${USER?} 这会把后面跟的空的环境变量等变量打印出来，注意加?<br>
3. 同&gt;&gt;连用，update文件的access/modification time<br>
: &gt;&gt; filename 效果同touch<br>
<br>
!的作用：<br>
inverts后面跟的命令的退出码，如 if [ $name != &quot;cow&quot; ];then ...<br>
<br>
*的作用：<br>
shell中，*表示0个或多个字符（和正则式中一致）<br>
**在shell计算中，用于指数运算<br>
<br>
?表示字符，和做测试的：<br>
shell中，?表示1个字符（不同于正则式中表示0个或1个）<br>
(1)同C语言三目运算符<br>
(2)在参数替代式中，测试前面的变量是否设置，见上面 : 的作用。<br>
<br>
${}参数替代式：就是把参数放里面，代表参数值<br>
$*,$@ 位置参数，两者只有在被引号引起的时候表现不同，因为前者把所有的参数当做一个参数，后者把每个参数都用引号隔开.你用for arg in &quot;$*&quot;，你就可以看出差别了，这句话只会循环一次。<br>
$?  刚启的进程或内置命令（无进程）的退出码<br>
$$  本脚本执行进程的id<br>
()  命令组，即subshell，如(a=hello; echo $a)，是启动一个子shell来执行命令组，所以，命令组中的变量，在()外面是看不到的<br>
<br>
数组初始化：<br>
array=(value1 value2 value3)<br>
<br>
brace常用：<br>
1. brace扩展：即{value1,value2}可被展开为value1或者value2<br>
grep linux file*.{txt,htm*} <br>
可以匹配txt和htm*结尾的，{}里面一定要有两个以上，只有一个是错的。<br>
echo {file1,file2}\:{\ A,&quot; B&quot;,' C'} 的结果是 file1: A file1: B file1: C file2: A file2: B file2: C<br>
注意：{}内的空格，需要用\, &quot;&quot;, ''来包含。<br>
<br>
2. brace代码块：<br>
{}也可以做代码块，与()的区别是，不会启动子shell，且{}可以用其他的变量，{}的变量也可以在外面可见，即都是全局的概念。<br>
另外，一个重要的特点是，{}可以被重定向，如:<br>
{<br>
read line1<br>
read line2<br>
} &lt; $file<br>
<br>
{<br>
echo &quot;haha&quot;<br>
echo &quot;hehe&quot;<br>
} &gt; $file<br>
<br>
3. brace用在find后，指代find找到的文件的路径集合<br>
find ./ -name &quot;*.h&quot; -exec ls -l {} \; <br>
其中 -exec引出后面的命令，{}指代找出的路径，;用于命令结尾，但是是给exec用的，所以用\转义一下，避免shell使用它。如果不用{}来处理文件，就不写{}。<br>
（-ok 有时替代-exec，它和exec一样，只是是交互性的，对每个路径，先提示你，再执行）<br>
<br>
小括号常用：<br>
1. 测试，还有[[]]这种测试。 <br>
2. 引用数组元素： 数组元素下标从0开始！！！！  array[0]=cow; echo ${array[0]}<br>
3. 正则式中用于给出一个字符集合，匹配其中任何一个<br>
<br>
command &amp;&gt;filename:  把在&gt;前加个&amp;，表示把stdout和stderr都导出到filename<br>
<br>
\&lt;\&gt; 用做正则式中的单词界限：<br>
grep '\&lt;the\&gt;' textfile 只查找the单词的，但不关心 *the* 的。<br>
<br>
<br>
dash的好处：<br>
1. 用stdout/stdin替代文件，并和| &gt; &lt; 结合完成处理功能：<br>
grep linux file1 | diff file2 -<br>
表示本来diff后跟两个文件做参数，但是用-替代，即原本期待为文件名的地方，这里将会取自标准输入。而这里由于shell管道，所以，标准输入其实来自|左边的命令。对于stdout也同样的道理，如果这里期望的是个写出的文件名，那么如果你用-替代的话，实际是会写到stdout上。但显然，打印到屏幕上，很多时候是没有用，所以一般是和管道或重定向符连用。<br>
注意，- 的作用是命令个人的行为，不是shell的操作符，和|&gt;&lt;等不一样。不过好多命令都提供-功能。<br>
2. 在参数默认值中：<br>
value=${1:-2} 表示，如果没有 $1的话，value值为2，否则为$1。2可以换为$引出的其他变量<br>
3. cd - 退回到上次cd的地方！ 等于 cd $OLDPWD<br>
<br>
<br>
<br>
第4章 变量和参数介绍<br>
$var 是 ${var}的简写，后者使得一些情况下不会出错<br>
设置一个变量为空，可以用var= 或者 unset var<br>
<br>
空白符和引号：<br>
a=$(ls -l)<br>
echo $a&#160;&#160;   #各种空白符被当作echo的参数的分割符了<br>
echo &quot;$a&quot; #各种空白符被保留，比如tab和换行会被正确打印<br>
<br>
bash变量是什么？<br>
是字符串，只有当某个变量的值全是数字时，才可能在某种context下进行比较和运算<br>
(1) 非数字和数字运算，结果为那个数字：<br>
e=&quot;&quot;  #令e为空字符串<br>
let &quot;e+=1&quot;<br>
echo &quot;e=$e&quot;  # e=1<br>
所谓数字，是说那个变量的值全部是数字。<br>
(2) 字符串和数字的简洁替代：<br>
c=BB34<br>
d=${c/BB/12} #表示把变量c中的BB换为12，这个和${1:-2}那种设置参数默认值的格式很像<br>
echo $d&#160;&#160;   #1234<br>
(3) 非数字和非数字运算:<br>
结果是未定义的<br>
<br>
<br>
特殊变量类型：<br>
(1)local: 函数或代码块中的变量<br>
(2)environmental：环境变量<br>
如$IFS，用于分割参数<br>
var=&quot;'(]\\{}\$\&quot;&quot;<br>
echo $var&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   # '(]\{}$&quot;<br>
echo &quot;$var&quot;&#160;&#160;&#160;&#160;&#160;&#160;   # '(]\{}$&quot; Doesn't make a difference.<br>
echo<br>
IFS='\'<br>
echo $var&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   # '(] {}$&quot; \ converted to space.<br>
echo &quot;$var&quot;&#160;&#160;&#160;&#160;&#160;&#160;   # '(]\{}$&quot;<br>
<br>
(3)positional: 位置变量<br>
$1, $2, ... $9, ${10}, ...  其中$0还是脚本在执行时写的路径<br>
$*和$@指代所有的变量，$#指代参数的个数（不包含$0）<br>
<br>
<br>
<br>
第5章 引号<br>
打印ascii字符\0表示八进制，\x表示十六进制<br>
echo -e &quot;\058\x59&quot; <br>
<br>
给变量用八进制，十六进制赋值：<br>
value=$'\058\x59'  #注意用$'..' 这种形式来做<br>
echo $value<br>
<br>
//// 无数个如何理解：<br>
比如这个例子： <br>
////z 其实是//z，因为从左往右，每一个/escape后面一个/，所以是//z。<br>
如果是/////z，结果还是//z，因为最右边一个/，由于是z，没有可escape的东西，它等效于没有它<br>
更多的/同理<br>
<br>
\ 转义换行符：<br>
var=\<br>
echo &quot;$var&quot;<br>
这个结果是\把换行符escape掉，似的 var=echo &quot;$var&quot; 就是说，有一个赋值操作，然后后面 &quot;$var&quot;是一个企图被执行的命令，这会报错，找不到这个命令。<br>
恩？看不出来吗，所有的命令，如果太长了，都要用\来换行，表示转义换行符，表示下面一行也要连接上来<br>
<br>
<br>
&quot;&quot;可以防止参数分割：（用''，或者用\转义一下中间的空格也一样）<br>
ls -l &quot;cow.txt sheep.txt&quot;  的结果是cow.txt sheep.txt作为一个文件名传给ls，然后ls报错，找不到这个文件。<br>
<br>
&quot;&quot;中只有三种特殊字符可以保持特殊：<br>
$,/,``<br>
<br>
<br>
第6章 退出<br>
默认的exit，返回的是exit上面最后一条命令的返回码。等于exit $?或者不写exit.<br>
重要的是，一个shell函数的返回码，也是用$?看的，所以shell函数的返回码，就是函数中最后一条命令的返回码。<br>
<br>
<br>
第7章 测试<br>
if测试的是命令exit后的返回值，为0为真。<br>
命令至少有这么几种：<br>
(1) test和[] ：这两个命令，都是shell内置命令（虽然在/usr/bin下都有，但是不会用系统那个），意义相同，参数都是“比较式”，返回0或非0。但注意 []中，不能用 &amp;&amp; || &gt; &lt;。所以，如果有多重条件，[]中用 -a 表示 and,-o表示or,或者在两个[]之间用 ||和&amp;&amp;<br>
(2) 其他任何系统命令<br>
(3) [[]] 这是bash扩展的运算符，可以看做内置命令，参数也是“比较式”，好处是和C语言语法近似：<br>
&amp;&amp; || &gt; &lt; 可以在[[]]中用，但在[]中会报错.所以,实际上[[]]啥都可以用!!<br>
(4) (())这个我发现很有用，它用于测试数学表达式的值，只用 &lt; &lt;= &gt; &gt;= 这几个，可以用在if或者for,while中！！不能用-引出的，形式上和C语句相似，所以看起来只是[[]]的一部分功能，但是和C写法一样！！<br>
<br>
if基本语法：<br>
if [ condition ];then<br>
cmd1<br>
cmd2<br>
elif [ condition ];then<br>
cmd3<br>
cmd4<br>
else<br>
cmd5<br>
fi<br>
<br>
<br>
运算符号：<br>
1. file test operator：n多，可联系的是，在我们经常用的find命令中，用 -type 参数给出的也有文件类型。<br>
2. comparison operator (这和我们的C体验相反,数字比较要用-引出的英文,字符串比较却用比较数字的 = &gt; &lt;等)<br>
integer: -eq -ne -gt -ge -lt -le &lt; &lt;= &gt; &gt;= （后面4个在(())中用到）<br>
string: = 和 == 一样 != &lt; &gt; -z -n<br>
3. ! 可以在1和2之前,表示取反<br>
4. compound comparison<br>
-a 用在[]或test中, 等于[[]]中用&amp;&amp;<br>
-o 用在[]或test中, 等于[[]]中用||<br>
例子: if [ -f /usr/bin/netscape -a -f /usr/share/doc/HTML/index.html ];then ...<br>
<br>
<br>
测试式中的变量,一定要加&quot;&quot;,因为有很多说不清楚的历史设计问题,导致加与不加,结果不同!!!!<br>
比如你可以测试下一个未定义的变量是否为空,你用[ -n $string ]和[ -n &quot;$string&quot; ]的结果是不同的,前者非空,后者为空.书上的解释是: [ -n $string ]其实-n看到的是],所以认为非空,这真是好笑.<br>
<br>
<br>
第8章 操作符<br>
** 指数<br>
<br>
一些位运算,和C一样,参见P59<br>
<br>
数学运算方式:<br>
(1) 整数运算:<br>
除了let比较简洁,$(())比较熟悉之外,在书57页还介绍了好多其他的方法,我去,真不人性化,懒得理<br>
(2) 浮点运算:<br>
shell不支持!!! 只能用外置命令,如bc<br>
如果把一个“浮点数”赋为一个变量，那个变量仅仅是一个带点的字符串。<br>
<br>
以任意进制赋值的方法:<br>
0开头的是8进制的,0x开头的是16进制的<br>
n#开头的是n进制的,比如2#11表示3.但是n的范围是2到64<br>
注意,赋值可用 let 形式,直接var=n#11 这只会被当做字符串.<br>
<br>
<br>
<br>
四、进阶：<br>
<br>
第9章 变量重访问<br>
内部变量：一大堆，P64开始，<br>
有好多有趣和有用的，其中有个IFS(input filed separator)，这个作用是设置其他的分割参数的，取代默认的白空格.<br>
还有$SECONDS，居然是保存这个脚本到现在执行了的秒数<br>
$! 在后台跑的最后一个任务的PID<br>
$$ 当前这个脚本的PID，这个拿来，常作为唯一标识，比如创建临时文件<br>
<br>
shell的字符串处理：<br>
有大量内置的字符串处理，基本就是用${.....}模样的式子，或者用expr也可以处理。除了一些简单的，如字符串长度外，他们不太统一，难记，比较混乱。<br>
其实，在上面已经接触过一些简单的了，比如${string/substring/replacement}做替换。如果要查阅，见P80<br>
如果不考虑效率 和书写简介，还是用awk吧，由于awk期望文件名做参数，用法如下：<br>
String=23skidoo1<br>
mv cow.txt `echo | awk '{print substr(&quot;'&quot;${String}&quot;'&quot;,3,4)}'`<br>
这里，mv的第二个参数是用echo来使得awk不必等待文件，但是注意到这里其实是有两''，它们之间是&quot;${String}&quot;，这就是命令的构造法！！！ 以前我的思路是echo $String | awk ... 这样来处理也行。但是我们看到，虽然你对awk熟悉，这样写远远没有shell内置的来的简洁。<br>
<br>
参数替代<br>
如${1:-2}这种上面已经见过了，就是参数1没有设置的话，另其值为2。还有其他意义的替代，见P85，他们的好处是，不必写复杂一些的if或case语句，一句话就搞定。缺点当然是不直观，只有经常用他们的人才会记得住。<br>
<br>
长度：<br>
${#var} 返回 var字符串的长度<br>
${#array[*]} 和 ${#array[@]} 返回array数组中元素个数<br>
<br>
随机数：<br>
$RANDOM 这个东西，你每访问一次就是一个随机数，范围为 0-32767 (14位)<br>
注意的是：这个东西，和C的 random/srandom函数不同，C中的表现是，你先用srandom设置一个seed，然后用random就可以返回一系列随机数了，默认的seed为1，就是你不调用srandom的话。这样，每次运行C程序，你得到的是一个相同的随机序列。但是bash的$RANDOM已经包含了&quot;srandom&quot;了，即：每次运行shell，序列是不一样的！！！！！！ 除非你自己指定RANDOM的seed。指定方法就是直接对RANDOM赋值，比如RANDOM=1.<br>
<br>
seed随机化：<br>
我觉得可以用 date +%s 返回的秒数即可。但是书上从/dev/urandom取这个数，我汗，代码如下：<br>
SEED=$(head &#8722;1 /dev/urandom | od &#8722;N 1 | awk '{ print $2 }')<br>
<br>
<br>
<br>
<br>
第10章 循环和分支<br>
写个典型的while循环吧：<br>
while [ &quot;$count&quot; -lt &quot;$MAXCOUNT&quot; ]<br>
do<br>
... #do sth<br>
let &quot;count += 1&quot;<br>
done<br>
<br>
再看看for循环：<br>
for i in &quot;1 2 3&quot; 和 for i in 1 2 3 效果是不同的。<br>
前者由于加了引号，将是一个东西而已，只循环一次。注意，这里&quot;1 2 3&quot;可能是一个变量，如 $files，它可能包含一些由白空格分开的元素，这都没有关系，关系只是，$files 本身在for语句中，是否用&quot;&quot;包围起来了，这个才决定循环一次，还是多次。<br>
另外，for中可以用shell匹配，如 for file in [jx]* 将匹配所有以j,x开头的文件，还可和find结合，处理一定的文件<br>
或者，复杂的命令也可： for name in $(awk 'BEGIN{FS=&quot;:&quot;}{print $1}' &lt; &quot;$PASSWORD_FILE&quot; )<br>
最后，写个更惊奇的吧： ———— 原来 for可以利用(())来写成C格式的for啊，以前一直被一些书误导了...方便吧...好吧，while中一样可以用：<br>
for ((a=0;a&lt;10;a++))<br>
do<br>
echo $a<br>
done<br>
<br>
until的用法：<br>
until [ &quot;$var1&quot; = &quot;end&quot; ]<br>
do<br>
... # 输入end才退出<br>
done<br>
<br>
好吧，这里的continue n表示到第几层循环继续。最里面的循环为1，外面为2，类推。<br>
<br>
case语句其实和if不同，不侧重条件，它主要用于shell匹配！！！！<br>
如判断是否全为英文字母：<br>
case &quot;$1&quot; in<br>
*[!a-zA-Z]*|&quot;&quot;) echo &quot;cow!&quot;;;<br>
*)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;   echo &quot;OK&quot;;;<br>
esac<br>
<br>
<br>
第11章 内置命令<br>
echo 不说了，如果在shell里用echo，用的是系统内置的，不是系统的那个<br>
<br>
printf 只能说这个太好用了，和C相同，只是没有括号和分割的逗号<br>
printf &quot;Pi to 2 decimal places = %1.2f&quot; $PI<br>
<br>
sprintf ？木有sprintf，不过可以这样模拟：<br>
Pi12=$(printf &quot;%1.12f&quot; $PI)<br>
<br>
read 这个吗，很简单，有个-t用于timeout的，有个-n3用于一次读入3个字符，即读够自动退出！！！！这个够爽吧。<br>
不过这里给的例子是告诉我们，箭头等键的输入是3个字符，所以这里用 read -n3 来读取：<br>
arrowup='\[A'<br>
arrowdown='\[B'<br>
arrowrt='\[C'<br>
arrowleft='\[D'<br>
insert='\[2'<br>
delete='\[3'<br>
SUCCESS=0<br>
read -n3 key<br>
判断的语句可以用grep（其实用case更简单）<br>
echo &#8722;n &quot;$key&quot; | grep &quot;$arrowup&quot;<br>
if [ &quot;$?&quot; &#8722;eq $SUCCESS ]<br>
then<br>
echo &quot;Up&#8722;arrow key pressed.&quot;<br>
exit $SUCCESS<br>
fi<br>
<br>
用read来读取文件中的每一行，每一个字段（见一部分中的例子）<br>
如果你不用这种方法来作的话，那么大概只能用外置命令来做，除非你全部都用外置命令来做，否则你只是用外置命令取一行，再用shell处理的话，会导致重复调用外置命令。取某一行的命令，可以用sed的行号匹配等来轻易完成。<br>
<br>
pushd,popd,dirs 用于用一个栈保存你的cd记录，使得可以容易回到早先压入栈的路径里。pushd dir就是cd到dir，并且将这个路径压栈的意思，popd用于退出当前目录到上一个目录，并将当前路径出栈的意思。dirs列出当前栈的情况。<br>
<br>
set如果不带参数跑的话，是列出shell中所有设置的环境变量。如果带参数，有些复杂，不理会了。<br>
<br>
getopts 这个是shell内置的用于获取以-/+开头的option，它和getopt命令和库用法一致，需要的话见P143<br>
<br>
source和.：如果在命令行下，等于执行一个脚本，如果在文件中，等于包含入令一个脚本，比如共享的数据，或者函数。<br>
<br>
exec 这个就是替代shell进程本身，来执行一个命令，导致的结果是命令结束，&quot;shell&quot;结束。<br>
<br>
wait 等待进程终止，和API的wait是一样的，启动多条命令或子shell在后台运行，然后你再wait.注意，这里的wait，等待的是多条后台命令结束！！！！全部结束后，它才返回。<br>
典型的启动子shell来做并行计算如：<br>
(<br>
count=0<br>
while [ &quot;$count&quot; -lt 5 ]<br>
do<br>
echo 1<br>
sleep 1<br>
let &quot;count+=1&quot;<br>
done<br>
)&amp;<br>
<br>
(<br>
count=0<br>
while [ &quot;$count&quot; -lt 10 ]<br>
do<br>
echo 2<br>
sleep 1<br>
let &quot;count+=1&quot;<br>
done<br>
)&amp;<br>
<br>
wait<br>
echo &quot;fuck!&quot;<br>
<br>
<br>
<br>
job的标识见P153，其中$!表示最后一个后台任务的PID <a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/7c1f49332328ea4aac4b5f1b.html">阅读全文</a>
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/category/%D6%AA%CA%B6%CC%E5%CF%B5">知识体系</a>&nbsp;<a href="http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/7c1f49332328ea4aac4b5f1b.html#comment">查看评论</a>]]></description>
        <pubDate>2009-07-05  10:17</pubDate>
        <category><![CDATA[知识体系]]></category>
        <author><![CDATA[00企鹅]]></author>
		<guid>http://hi.baidu.com/00%C6%F3%B6%EC/blog/item/7c1f49332328ea4aac4b5f1b.html</guid>
</item>


</channel>
</rss>