2007年10月26日星期五

“串行”为什么会走红?[转载]

http://article.ednchina.com/PC/20061008114051.htm
近两年,大家听得最多的一个词可能就是串行传输了。从技术发展的情况来看,串行传输方式大有彻底取代并行传输方式的势头,USB取代 IEEE 1284,SATA取代PATA,PCI Express取代PCI……
  从原理来看,并行传输方式其实优于串行传输方式。通俗地讲,并行传输的通路犹如一条多车道的宽阔大道,而串行传输则是仅能允许一辆汽车通过的乡间公路。以古老而又典型的标准并行口(Standard Parallel Port)和串行口(俗称COM口)为例,并行接口的位宽为8,数据传输率高;而串行接口只有1位,数据传输速度低。在串行口传送1位的时间内,并行口可以传送一个字节。当并行口完成单词“advanced”的传送任务时,串行口中仅传送了这个单词的首字母“a”。

图1:H6A-2-1.TIF 并行接口速度是串行接口的8倍
  那么,现在的串行传输方式为何会更胜一筹呢?
  一、并行传输技术遭遇发展困境
  电脑中的总线和接口是主机与外部设备间传送数据的“大动脉”,随着处理器速度的节节攀升,总线和接口的数据传输速度也需要逐步提高,否则就会成为电脑发展的瓶颈。图2 PC总线的发展
我们先来看看总线的情况。1981年第一台PC中以ISA总线为标志的开放式体系结构,使用了ISA总线,数据总线为8位,工作频率为8.33MHz,这在当时却已经算作“先进技术(Advanced Technology)”了,所以ISA总线还有另一个名字“AT总线”。到了286时,ISA的位宽提高到了16位,为了保持与8位的ISA兼容,工作频率仍为8.33MHz。ISA总线虽然只有16MBps的数据传输率,但直到386时代,都一直是主板与外部设备间最快的数据通道。
  到了486时代,同时出现了PCI和VESA两种更快的总线标准,它们具有相同的位宽(32位),但PCI总线能够与处理器异步运行,当处理器的频率增加时,PCI总线频率仍然能够保持不变,可以选择25MHz、30MHz和33MHz三种频率。而VESA总线与处理器同步工作,因而随着处理器频率的提高,VESA总线类型的外围设备工作频率也得随着提高,适应能力较差,因此很快失去了竞争力。PCI总线标准成为Pentium时代PC总线的王者,硬盘控制器、声卡到网卡,全部使用PCI插槽。而显卡方面对数据传输速度要求更高,出现了专用的AGP,
  并行数据传输技术向来是提高数据传输率的重要手段,但是,进一步发展却遇到了障碍。首先,由于并行传送方式的前提是用同一时序传播信号,用同一时序接收信号,而过分提升时钟频率将难以让数据传送的时序与时钟合拍,布线长度稍有差异,数据就会以与时钟不同的时序送达,另外,提升时钟频率还容易引起信号线间的相互干扰,导致传输错误。因此,并行方式难以实现高速化。从制造成本的角度来说,增加位宽无疑会导致主板和扩充板上的布线数目随之增加,成本随之攀升。
  在外部接口方面,我们知道IEEE 1284并行口的速率可达300kBps,传输图形数据时采用压缩技术可以提高到2MBps,而RS-232C标准串行口的数据传输率通常只有20kbps,并行口的数据传输率无疑要胜出一筹。因此十多年来,并行口一直是打印机首选的连接方式。对于仅传输文本的针式打印机来说,IEEE 1284并行口的传输速度可以说是绰绰有余的。但是,对于近年来一再提速的激光打印机来说,情况发生了变化。笔者使用爱普生6200L在打印2MB图片时,速度差异不甚明显,但在打印7.5MB大小的图片文件时,从点击“打印”到最终出纸,使用USB接口用了18秒,而使用并行口时,用了33秒。这一测试结果说明,现行的并行口对于时下流行的激光打印机来说,已经力难胜任了。
  二、USB,串行接口浴火重生
  凤凰涅槃,浴火重生。1995年,由Compaq、Intel、Microsoft和NEC等几家公司推出的USB接口首次出现在PC机上,1998年起即进入大规模实用阶段,作为IEEE 1284并行口和RS-232C串行口的接班人,USB现在已经呈现出大红大紫了。

USB虽然只有一位的位宽,但数据传输速度却比并行口要高,而且具有很大的发展空间。USB设备通信速率的自适应性,使得它可以自动选择HS(High-Speed,高速,480 Mbps)、FS(Full-Speed,全速,12Mbps)和LS(Low-Speed,低速,1.5Mbps)三种模式中的一种。USB总线还具有自动的设备检测能力,设备插入之后,操作系统软件会自动地检测、安装和配置该设备,免除了增减设备时必须关闭PC机的麻烦。

图3 采用差模信号传送方式的USB 图4 差分传输方式具有更好的抗干扰性能
USB接口之所以能够获得很高的数据传输率,主要是因为其摒弃了常规的单端信号传输方式,转而采用差分信号(differential signal)传输技术,有效地克服了因天线效应对信号传输线路形成的干扰,以及传输线路之间的串扰。USB接口中两根数据线采用相互缠绕的方式,形成了双绞线结构,如图3。
  图4是由两根信号线缠绕在环状铁氧体磁芯上构成的扼流线圈。在单端信号传输方式下,线路受到电磁辐射干扰而产生共模电流时,磁场被叠加变成较高的线路阻抗,这样虽然降低了干扰,但有效信号也被衰减了。而在差动传输模式下,共模干扰被磁芯抵消,但不会产生额外的线路阻抗。换句话说,差动传输方式下使用共模扼流线圈,既能达到抗干扰的目的,又不会影响信号传输。
  差分信号传输体系中,传输线路无需屏蔽即可取得很好的抗干扰性能,降低了连接成本。不过,由于USB接口3.3V的信号电平相对较低,最大通信距离只有5m。USB规范还限制物理层的层数不超过7层,这意味着用户可以通过最多使用5个连接器,将一个USB设备置于距离主机最远为30m的位置。
  为了解决长距离传输问题,扩展USB的应用范围,一些厂商在USB规范上添加了新的功能,例如Powered USB和Extreme USB,前者加大了USB的供电能力,后者延长了USB的传输距离。譬如采用CAT5电缆和RJ45连接器,可以简单地将扩展至100m;采用光纤更可扩展至2km,只是成本比CAT5更高。
小知识:双绞线,绞在一起有什么好?
  双绞线互相缠绕的目的是利用铜线中电流产生的电磁场互相作用抵消邻近线路的干扰并减少来自外界的干扰。每对线在每英寸长度上相互缠绕的次数决定了抗干扰的能力和通讯的质量,缠绕得越紧密其通讯质量越高,所支持的数据传输率越高,制造成本当然也相应提高。双绞线即使外面没有屏蔽层,也能获得很好的抗干扰性能,所以局域网中选用CAT5非屏蔽双绞线(UTP)便能满足传输100Mbps信号的要求,且通信距离可以达到100m。
  三、差分信号技术:高速信号传输的金钥匙
  电脑发展史就是追求更快速度的历史,随着总线频率的提高,所有信号传输都遇到了同样的问题:线路间的电磁干扰越厉害,数据传输失败的发生机率就越高,传统的单端信号传输技术无法适应高速总线的需要。于是差分信号技术就开始在各种高速总线中得到应用,我们已经知道,USB实现高速信号传输的秘诀在于采用了差分信号传输方式。

图5 差分信号传输电路

图6 单端信号传输
图7 差分信号传输
差分信号传输技术是20世纪90年代出现的一种数据传输和接口技术,与传统的单端传输方式相比,这种技术具有低功耗、低误码率、低串扰和低辐射等特点,其传输介质可以是铜质的PCB连线,也可以是平衡电缆,最高传输速率可达1.923Gbps。Intel倡导的第三代I/O技术(3GIO),其物理层的核心技术就是差分信号技术。那么,差分信号技术究竟是怎么回事呢?
  我们知道,在传统的单端(Single-ended)通信中,一条线路来传输一个比特位。高电平表示1,低电平表示0。倘若在数据传输过程中受到干扰,高低电平信号完全可能因此产生突破临界值的大幅度扰动,一旦高电平或低电平信号超出临界值,信号就会出错,如图6所示。 在差分传输电路中,输出电平为正电压时表示逻辑“1”,输出负电压时表示逻辑“0”,而输出“0”电压是没有意义的,它既不代表“1”,也不代表“0”。而在图7所示的差分通信中,干扰信号会同时进入相邻的两条信号线中,在信号接收端,两个相同的干扰信号分别进入差分放大器的两个反相输入端后,输出电压为0。所以说,差分信号技术对干扰信号具有很强的免疫力。对于串行传输来说,LVDS能够低于外来干扰;而对于并行传输来说,LVDS可以不仅能够抵御外来干扰,还能够抵御数据传输线之间的串扰。
  因为上述原因,实际电路中只要使用低压差分信号(Low Voltage Differential Signal,LVDS),350mV左右的振幅便能满足近距离传输的要求。假定负载电阻为100Ω,采用LVDS方式传输数据时,如果双绞线长度为10m,传输速率可达400 Mbps;当电缆长度增加到20m时,速率降为100 Mbps;而当电缆长度为100m时,速率只能达到10 Mbps左右。
  LVDS最早由美国国家半导体公司提出的一种高速串行信号传输电平,由于它传输速度快,功耗低,抗干扰能力强,传输距离远,易于匹配等优点,迅速得到诸多芯片制造厂商和应用商的青睐,并通过TIA/EIA(Telecommunication Industry Association/Electronic Industries Association)的确认,成为该组织的标准(ANSI/TIA/EIA-644 standard)。
  在近距离数据传输中,LVDS不仅可以获得很高的传输性能,同时还是一个低成本的方案。LVDS器件可采用经济的CMOS工艺制造,并且采用低成本的3类电缆线及连接件即可达到很高的速率。同时,由于LVDS可以采用较低的信号电压,并且驱动器采用恒流源模式,其功率几乎不会随频率而变化,从而使提高数据传输率和降低功耗成为可能。因此,USB、SATA、PCI Express以及HyperTransport普遍采用LVDS技术,LCD中控制电路向液晶屏传送像素亮度控制信号,也采用了LVDS方式。
四、新串行时代已经到来 差分传输技术不仅突破了速度瓶颈,而且使用小型连接可以节约空间。因此,近年来,除了USB和FireWire,还涌现出很多以差分信号传输为特点的串行连接标准,几乎覆盖了主板总线和外部I/O端口,呈现出从并行整体转移到新串行时代的大趋势,串行接口技术的应用在2005年将进入鼎盛时期(图8)。
图8 所有的I/O技术都将采用串行方式
  ● LVDS技术,突破芯片组传输瓶颈
  随着电脑速度的提高,CPU与北桥芯片之间,北桥与南桥之间,以及与芯片组相连的各种设备总线的通信速度影响到电脑的整体性能。可是,一直以来所采用的FR4印刷电路板因存在集肤效应和介质损耗导致的码间干扰,限制了传输速率的提升。
   在传统并行同步数字信号的速率将要达到极限的情况下,设计师转向从高速串行信号寻找出路,因为串行总线技术不仅可以获得更高的性能,而且可以最大限度地减少芯片管脚数,简化电路板布线,降低制造成本。Intel的PCI Express、AMD的HyperTansport以及RAMBUS公司的redwood等第三代I/O总线标准(3GI/O)不约而同地将低压差分信号(LVDS)作为新一代高速信号电平标准。
图9 PCI Express 1X数据通道
  一个典型的PCI Express通道如图9所示,通信双方由两个差分信号对构成双工信道,一对用于发送,一对用于接收。4条物理线路构成PCI Express 1X。PCI Express 标准中定义了1X、2X、4X和16X。PCI Express 16X拥有最多的物理线路(16×4=64)。
  即便采用最低配置的1X体系,因为可以在两个方向上同时以2.5GHz的频率传送数据,带宽达到5Gbps,也已经超过了传统PCI总线1.056Gbps(32bit×33MHz)的带宽。况且,PCI总线是通过桥路实现的共享总线方式,而PCI Express采用所谓的“端对端连接”(如图10),每个设备可以独享总线带宽,因此可以获得比PCI更高的性能。图10 PCI Express端对端连接消除了桥路
AMD的HyperTransport技术与PCI Express极其相似,同样采用LVDS数据通道,其工作频率范围从200MHz到1GHz,位宽可以根据带宽的要求灵活选择2、4、8、16或32位。HyperTransport技术现在被用于南北桥之间的快速通信,今后还将用于其它芯片间的连接。
  ● Serial ATA,为高速硬盘插上翅膀
在ATA-33之前,一直使用40根平行数据线,由于数据线之间存在串扰,限制了信号频率的提升。因此从ATA-66开始,ATA数据线在两根线之间增加了1根接地线正是为了减少相互干扰。增加地线后,数据线与地线之间仍然存在分布电容C2,还是无法彻底解决干扰问题,使得并行ATA接口的最高频率停留在133MHz上。除了信号干扰这一根本原因之外,并行PATA 还存在不支持热插拔和容错性差等问题,采用Serial ATA才完成脱胎换骨的蜕变,使问题得到了解决。
  Serial ATA 是Intel 公司在IDF 2000 上推出的概念,此后Intel 联合APT、Dell、IBM、Seagate以及Maxtor等几家巨头,于2001年正式推出了SATA 1.0 规范。而在IDF2002春季论坛上,SATA 2.0 规范也已经公布。
  Serial ATA接口包括4根数据线和3 根地线,共有7 条物理连线。目前的SATA 1.0标准,数据传输率为150MBps,与ATA-133接口133MBps的速度略有提高,但未来的SATA 2.0/3.0可提升到300MBps以至600MBps。从目前硬盘速度的增长趋势来看,SATA 标准至少可以满足未来数年的要求了。
图11 并行ATA的线间串扰
  ● FireWire,图像传输如虎添翼
  FireWire(火线)是1986年由苹果电脑公司起草的,1995年被美国电气和电子工程师学会(IEEE)作为IEEE 1394推出,是USB之外的另一个高速串行通信标准。FireWire最早的应用目标为摄录设备传送数字图像信号,目前应用领域已遍及DV、DC、DVD、硬盘录像机、电视机顶盒以及家庭游戏机等。
  FireWire传输线有6根电缆,两对双绞线形成两个独立的信道,另外两根为电源线和地线。SONY公司对FireWire进行改进,舍弃了电源线和地线,形成只有两对双绞线的精简版FireWire,并给它起了个很好听的名字i.Link。
  FireWire数据传输率与USB相当,单信道带宽为400Mbps,通信距离为4.5m。不过,IEEE 1394b标准已将单信道带宽扩大到800Mbps,在IEEE 1394-2000新标准中,更是将其最大数据传输速率确定为1.6Gbps,相邻设备之间连接电缆的最大长度可扩展到100m。
  五、串行口能红到哪天?
  阅读本文之后,如果有人问你关于串行通信与并行通信哪个更好的问题,你也许会脱口而出:串行通信好!但是,我要告诉你,新型串行口之所以走红,那是因为采用了四根信号线代替了传统两根信号线的信号传输方式,由单端信号传输转变为差分信号传输的原因,而“在相同频率下并行通信速度更高”这个基本的道理是永远不会错的,通过增加位宽来提高数据传输率的并行策略仍将发挥重要作用。
  技术进步周而复始,以至无穷,没有一项技术能够永远适用。电脑技术将来跨入THz时代后,对信号传输速度的要求会更高,差分传输技术是否还能满足要求?是否需要另一种更好的技术来完成频率的另一次突破呢?让我们共同关注。

2007年8月20日星期一

在Perl中获取当前目录的完整路径

有两种方法:
1. use Cwd;
my $dir = getcwd;
#$dir中即为当前目录的完整路径信息。

2. my $dir = $ENV{'PWD'};
#ENV是一个散列,用于存放环境变量。$PWD是Linux的环境变量,表示当前所在目录。

若当前目录为/usr/lib/, 则上面的$dir = /usr/lib

2007年7月9日星期一

《Learning Perl》学习笔记 -- 其余几章

第十三章 处理文件和目录
介绍如何删除文件、重命名文件、链接和文件、建立和删除目录等。比较有用的是介绍了File::Basename(用来获得文件的基名和目录名)和File::Spec模块(用来处理文件规范)。使用命令perldoc File::Basename获得模块的使用方法。
模块声明:在程序的顶部附近通过use命令来声明它
use File::Basename;
在编译的时候,Perl看到这行,就会将这个模块装载进来。

以下四章对我来说有些深奥了,没有仔细研究,以后如果用到,再好好看看:
第十四章 进程管理
第十五章 字符串和排序
第十六章 简单数据库
第十七章 一些高级Perl技术


《Learning Perl》学习笔记 -- 第十二章 目录操作

本章介绍如何改变目录树,如何使用目录句柄以读取目录中的文件列表等。

1.改变目录树
chdir操作符可以改变工作目录。就像Unix中shell的cd命令:
chdir "/etc" or die "can not chdir to /etc:$!";
2.目录句柄
可以使用目录句柄(directory handle)来指定目录的文件列表。目录句柄在外表和操作方式上都很像文件句柄,你可以打开它(opendir)、读取它(readdir)还可以关闭它(closedir)。不过与读出文件的内容不同的是,你读出来的是目录中的文件(和其它东西)的名字。譬如:
my $mydir = "/etc";
opendir MYDIR, $mydir or die "Can not open $mydir:$!";
foreach $file (readdir MYDIR) {
print "one file in $mydir is $filen";
}

这里需要注意的一点是readdir操作符返回的文件名没有路径名部分,它仅仅是目录内的名字。因此,在上例中,对于/etc/passwd,$file的值为passwd而不是/etc/passwd。所以,需要我们自己把名字补齐来以得到全名:
my $mydir = "/etc";
opendir MYDIR, $mydir or die "Can not open $mydir:$!";
while (my $name = readdir MYDIR) {
next if $name =~ /^./; #跳过以点开头的文件
$name = "$mydir/$name"; #补上路径
next unless -f $name and -r $name; #只要可读文件
...
}

《Learning Perl》学习笔记 -- 第十一章 文件句柄和文件测试

本章介绍如何读写文件及测试文件的类型,是日常编程中重要的内容。

1.文件句柄的概念
文件句柄(filehandle)是Perl程序中的一个名字,表示你的Perl进程与外面世界的I/O连接。也就是说,它是一个连接的名字,并不一定是一个文件的名字。
文件句柄
文件<====================>进程
2.文件句柄的命名
命令文件句柄的方式和其它Perl标识符一样(字母、数字和下划线,但不能以数字开始),但文件句柄名没有前缀字符。为了避免和Perl的保留字(关键字)冲突,一般文件句柄名全部用大写字母。
3.打开一个文件句柄
open MYFILE " > myfile" or die "Cannot Create myfile:$!";
其中,MYFILE是文件句柄名,myfile是实际的文件名,>表示向该文件中写入数据(<表示从该文件中读取数据,>>表示向该文件中追加数据);若打开文件出错,会执行die语句,终止程序执行,并给出错误信息,$!用于给出错误信息。
4.关闭一个文件句柄
close MYFILE;
5.使用文件句柄
一旦打开了一个文件句柄,就可以读入行,像使用STDIN从标准输入读取一样,譬如:
open MYFILE " > myfile" or die "Cannot Create myfile:$!";
while (<MYFILE>) {
...
}
一个为写入或追加而打开的文件句柄可以和print或printf一起使用,紧跟在其后但在参数列表之前:
print LOG "Captain's log, stardate 3.14159n"; # 输出到LOG
print STDERR "%d percent complete.n", $done/$total*100;
6.文件测试
Perl有一组完整的测试,可以用它们了解文件的信息,譬如某个文件是否存在,是否可读、可写等。所有的文件测试都有一个短横和一个字母,它们是测试的名字,后面是一个要测试的文件名或文件句柄,一般会返回一个真/假值。用法如下:
if (-e $filename) {
...
}
常用的文件测试及它们的含义:
-r : 文件或目录对该用户或组可读
-w : 文件或目录对该用户或组可写
-x : 文件或目录对该用户或组可执行
-o :文件或目录被该用户所有
-e :文件或目录存在
-z :文件存在,大小为零(对目录总为假)
-s :文件或目录存在,大小非零(单位为字节)

-f :条目是个普通文件

-d :条目是个目录
-l :条目是个符号链接

2007年7月6日星期五

《Learning Perl》学习笔记 -- 第十章 更多的控制结构

本章介绍了一些不常用的控制结构,在日常编程中基本上都不会用到,下面介绍几个可能用到的控制结构。

1.elsif子句
if (...) {
}
elsif (...) {
}
else {
}
2.for控制结构
和C语言中的类似
for (initialization;test;increment) {
...
}


2007年5月29日星期二

《Learning Perl》学习笔记 -- 第九章 使用正则表达式

本章介绍如何在Perl中使用正则表达式,介绍了“查找”(m//)、“替换”(s///)及split操作符、join函数的用法。

1.使用m//进行匹配

前面两章介绍的模式,都是在一对斜杠中的,如/fred/。但这实际上是m//(模式匹配)操作符的一个快捷方式,只所以说是快捷方式是因为可以选择任何定界符对把内容括住,而当选择了斜杠作为定界符时,就可以省略开始的m。譬如,m#fred#和/fred/是等价的。

有几个选项修饰符字母,也可称为标志符(flag),可以把它们附加在正则表达式的结束定界符后面,以改变表达式的缺省行为。

/i:进行不区分大小写的匹配,如/fred/i;

/s:使点号(.)可以进行任何字符的匹配,点号原先不能匹配换行符,加上这个标志符后,就可以匹配任何字符,如/fred.*lee/s;

可以组合使用标志符,组合的顺序不重要,譬如/fred/is和/fred/si是等价的。

2.绑定操作符=~

与$_匹配只是个缺省操作。绑定操作符(binding operator)=~告诉Perl用右侧的模式匹配左侧的字符串,而不是匹配$_。譬如:

if ($some_other =~ /brub/) {

...

}

3.在模式中替换

这里的替换指的是双引号替换,即在正则表达式中,可以把变量替换为它实际的值。进行变量替换时,需要将变量放在小括号中。譬如:

my $what = "larry";

if (/^($what)/) {

...

}

4.匹配变量和记忆的持久性

在正则表达式中使用\n对匹配的字符串进行反向引用,而在Perl中,使用$n来引用匹配的字符串。两者的区别是,\n回指当前正在进行匹配的正则表达式的第n个记忆,$n表示一个已经完成的模式匹配的第n个记忆。两者有个时间差,即在同一时刻指的并不是同一个字符串。譬如:

$_ = "Hello there, neighbor";

if (/\s(\w+),/) { # 记住空格和逗号之间的单词

print "the word was $1\n"; # $1 = Hello there

}

匹配变量一般保留到下一次模式匹配成功,即一个不成功的匹配会维持以前记忆的原状,但一个成功的匹配则全部重新设置它们。这是模式匹配一般总是在if或while的条件表达式中的一个原因。由于记忆不会永远保持,所以一般在模式匹配的后面马上使用这个记忆的变量,或者将这个记忆的变量拷贝到一个普通变量中,以便后面继续使用。譬如:

if ($wilma =~ /(\w+)/) {

my $wilma_word = $1;

...

}

在Perl中,有三个系统定义的模式匹配变量,即你无须自己定义这些变量即可使用它们:

$`:保存正则表达式引擎在找到匹配之前需要跳过的部分;

$&:保存实际与模式匹配的那部分字符串;

$':保存模式没有到达的字符串的剩余部分;

将这三个字符串按顺序连在一起,你总会得到原字符串:$`$&$'。

5.用s///进行替换

使用s///可以用一个替换字符串来替换一个变量匹配模式的部分,譬如:

$_ = "He's out bowling with Barney tonight.";

s/Barney/Fred/; # 用Fred替换Barney

s///有一个返回值,如果替换成功,则返回真;否则,返回假。

和m//类似,s///可以使用绑定操作符=~ 改变匹配的变量,譬如:

$file_name =~ s/Barney/Fred/; #在$file_name中查找Barney并将其替换为Fred

和m//类似,s///也可以使用不同的定界符,此处不再赘述。

和m//类似,s///使用一组标志符来改变缺省行为:

/g:进行全局替换,如果没有这个标志,则s///仅替换匹配的第一个模式;

/i,/s:用法和m//中的类似,此处不再赘述;

6.大小写转换

在替换的时候,可能经常希望替换字符采用了合适的大写(或小写,依需要而定)。这很容易用Perl来完成,即通过一些反斜杠转义。

\U转义符强制后面的字符都用大写,譬如:

$_ = "I saw Barney with Fred";

s/(fredbarney)/\U$1/gi; #$_现在是"I saw BARNEY with FRED."

\L转义符强制后面的字符都用小写;

缺省情况下,U和L会影响其后的所有(替换)字符串,除非使用\E关闭大小写转换,譬如:

$_ = "I saw Barney with Fred";

s/(\w+) with (\w+)/\U$2\E with $1/i; # $_现在是"I saw FRED with Barney."

当写成小写的形式时(\l\u),它们只影响下一个字符,譬如:

$_ = "I saw barney with fred";

s/(fredbarney)/\u$1/gi; # $_现在是"I saw Barney with fred."

\u\L(或\L\u)表示全部小写,但是第一个字符大写;

7.split操作符

split操作符把一个字符串按照分割子(separator)分开。格式如下:

@result = split /separator/, $string;

split操作符在字符串中用模式/separator/扫一遍,返回一个由分割子分割的字段(子字符串)的列表。每当模式匹配时,就是一个字段的结束和下一个字段的开始,因此,任何可以匹配模式的东西都不会出现在返回的字段中。譬如:

@result = split /:/, "abc:def:g:h"; # @result = ("abc", "def", "g","h")

8.join函数

join函数完成split操作符相反的功能:split把一个字符串分成若干片段,而join则把一组片段粘合起来形成一个字符串。格式如下:

my $result = join $glue, @pieces;

join的第一个参数是粘合串,它可以是任何字符串。另一个参数是由片段组成的一个列表,join把粘合字符串放在片段之间。譬如:

my $x = join ":", 4,6,8,10,12; # $x = "4:6:8:10:12"

2007年5月28日星期一

《Learning Perl》学习笔记 -- 第八章 正则表达式提高

本章介绍了字符类、通用数量符、锚位符、记忆的小括号、反向引用及优先级等重要内容,前面的内容好懂、易记,后面的“记忆的小括号、反向引用和优先级”的内容需要重点理解与掌握,有一定难度。

1.字符类

字符类(character class),即在一对中括号([])中列出的所有字符,可以匹配类中的任何单个字符,它只匹配一个字符,但该字符必须在表中。譬如[abcdwxyz]或[a-dw-z](可用短横-指定一个字符范围,上面两个字符类是等价的)。

可以用双引号字符串中类似的字符快捷方式来定义一个字符类,譬如[000-177]匹配任何7比特ASCII字符。

在字符类前加一个脱字符(^)可以反置它,即只匹配不包含在中括号中的任何单个字符。譬如[^abc]匹配除了a、b和c之外的任何字符。注意,脱字符必须出现在中括号内字符的最前面,否则不具备反置的含义。如[a^bc]表示匹配a、^、b和c中的任一字符。

字符类的快捷方式:

d:匹配所有数字的字符类,等价于[0-9];d是digital的缩写

w:匹配所谓的“单词”字符,即普通字母、数字和下划线,等价于[A-Za-z0-9_];w是word的缩写

s:匹配空白,包括换页符、制表符、换行符、回车符和空个字符,等价于[ftnr ];s是space的缩写

D:匹配所有非数字字符类,即d的反置形式,等价于[^d];

W:匹配所有的非“单词”字符,即w的反置形式,等价于[^w];

S:匹配所有的非空白字符,即s的反置形式,等价于[^s];

2.通用数量符

使用大括号({})中的一对由逗号隔开的数字来指定重复的最少和最多次数。

/a{N,M}/:匹配重复N到M次的字符a;

/a{N,}/:匹配重复次数大于等于N的字符a,没有上限;

/a{N}/:匹配重复次数等于N的字符a,精确匹配;

3.锚位符(anchor)

^:标志字符串的头,可以理解为标志行首,譬如/^fred/匹配以fred开头的行;

$:标志字符串的尾,可以理解为标志行尾,譬如/fred$/匹配以fred结束的行;

b:单词边界锚位符,标志单词的开始与结束,用于精确匹配单词(单词中只含有w类型的字符),譬如/bfredb/精确匹配单词fred;

B:非单词边界锚位符,可以看作b的反置形式;

4.记忆的小括号及反向引用

小括号的一个功能是把模式的一些部分组合起来,它的第二个作用是要求正则表达式引擎记住与小括号中的模式匹配的那部分子串。也就是说,它不是记住模式本身,而要记住相应的部分字符串。在用小括号进行分组时,它们自动具有记忆功能。

反向引用(backreference)就是回头引用当前模式处理过程中保存的记忆。反向引用由一个反斜杠来构成,譬如,1包含第一个正则表达式记忆(即被第一对小括号匹配的字符串部分)。

反向引用被用来匹配与模式在前面匹配的字符串完全一样的字符串,譬如/(.)1/匹配任何字符,后跟同一个字符,即匹配任何双字符(如aa,11,两个连续空格等)。

反向引用使用n来标记第n个正则表达式记忆,确定n的方法是:从左到右,只数左括号的个数即可。譬如,在模式/((fredwilma)(stone))/中,1表示最外层的小括号匹配的字符串部分,2表示(fredwilma)小括号匹配的字符串,3表示(stone)小括号匹配的字符串。

在使用八进制转义字符时,如果小于100,则最高位写0,如012,以避免被误当作反向引用。

5.优先级

在介绍优先级之前,需要了解所谓的原子(atom),它是构成模式最基本的片段,可以看作不可分割的一个最小单元。原子包括独立的字符、字符类和反向引用。

正则表达式的优先级分四个级别,优先级数字越低,级别越高:

1.小括号,用作分组和记忆。小括号中的任何东西比其它东西都更紧密地“粘在一起”;

2.数量符,包括星号(*)、加号(+)、问号(?)和大括号构成的数量符;

3.锚位符和字符串序列,即一个单词中的字母粘在一起的紧密程度与锚位符粘着字母的紧密程度一样;

4.最低的优先级是表示选择的竖线。

2007年5月27日星期日

《Learning Perl》学习笔记 -- 第七章 正则表达式的概念

笔者注:用过几次正则表达式后,为它的强大与灵活所折服,打算再深入研究一下,本书推荐了Jeffrey E.F.Friedl编著的《Mastering Regular Expression》,已经从图书馆借的,有空研读一下:P

本章主要介绍了正则表达式的概念,还介绍了正则表达式的一些基本要素,如元字符、数量符、模式分组、选择等。

1.正则表达式的概念

书中这段讲的很好,简明易懂,我就照抄了,呵呵

正则表达式(regular expression),在Perl中经常被成为模式(pattern),是与一个给定字符串匹配或不匹配的模板。也就是说,有无限数量可能的文本字符串。一个给定的模式把这个无限集合分成两个组:匹配的组和不匹配的组。不能有“可能”、“也许”、“似乎”之类的匹配:必须是要么匹配,要么不匹配。

正则表达式强调的是一种精确的概念。

2.使用简单的模式

要比较一个模式(正则表达式)和$_的内容,只需把模式放在一对斜杠(/)之间,如下所示:

$_ = "yabba dabba doo";

if (/abba/) {

...

}

表达式/abba/在$_中寻找这个四字符的字符串,如果找到了,返回真;否则,返回假。

这是一种默认模式,在下一章中将介绍如何在一个指定的变量中匹配特定的模式。

所有可以放在双引号字符串中的常见反斜杠转义符都可以被用在模式中。

3.元字符

正则表达式中有一组具有特殊意义的特殊字符,叫做元字符(metacharater)。

句号(.):匹配除了换行符(n)以外的任何单个字符;

反斜杠(\):在任何元字符前加一个反斜杠都会使得它不再特别;\.表示一个句号,\\表示一个反斜杠;

4.数量符(quantifier)

星号(*):匹配前面的条目零次或多次;

加号(+):匹配前面的条目一次或多次;

问号(?):匹配前面的条目零次或一次,即前面的条目是可选的;

这三个数量符都必须跟在某些东西的后面,因为它们就是表示前面的条目可能重复多少次。

5.模式中的分组

在正则表达式中,使用小括号("()")进行分组。譬如,模式/(fred)+/匹配类似于fredfredfred的字符串。

6.选择

竖线表示要么是左侧匹配,要么是右侧匹配,此时读做“或”,也就是说,如果模式中竖线左侧的部分不能匹配,那么右侧的部分就有机会进行匹配。

7.一个模式测试程序

该章给了一个有趣的模式测试程序,可以用来测试自己写的正则表达式是否可以如自己所愿、匹配需要匹配的东西。

#!/usr/bin/perl

while (<>) { #一次得到一个输入行

chomp;

if (/YOUR_PATTERN_GOES_HERE/) {

print "Matched: $`<$&>$'\n"; # <>之间、$后面的是与字符(&)

} else {

print "No match.\n";

}

}

2007年4月30日星期一

《Learning Perl》学习笔记 -- 第六章 I/O基础

本章主要讲述了如何从标准输入/文件中获得输入及如何向标准输出进行输出。

1.从标准输入进行输入

使用行输入操作符<STDIN>从标准输入中获得输入。

$line = <STDIN>; # 读入一行

在循环中使用:

while (<STDIN>) {
...
}


foreach (<STDIN>) {
...
}

使用这种写法,行输入的数据被存储在默认的标量变量$_中,当然也可以显式的将行输入数据赋给一个已定义的标量变量中,如$line。
上述两个循环的区别是:
while循环每次处理一行数据,而foreach循环会首先读入全部输入,然后在逐行处理。所以,如果输入的文件很大,最好使用while循环。

2.从钻石操作符(<>)进行输入

钻石操作符被设计用来处理命令行参数(或者称为“调用参数”),可以看作是特殊的行输入操作符。

例如:

./my_program fred barney betty

my_program是命令,后面的fred、barney和betty是这个命令的命令行参数,可能是三个文件的名字(若从标准输入进行输入,则用-表示)。钻石操作符的作用是从命令行参数中连续获得输入数据,好像将这三个文件合并成一个大的文件后,逐行输入似的。如下所示:

while (<>) {

chomp;

print "It was $_ that I saw!n";

}

这个循环的会依次从fred、barney和betty这三个文件中读取输入,然后逐个打印出来。

3.调用参数

命令的调用参数实际存储在Perl预设的数组@ARGV中,钻石操作符从@ARGV数组中获得命令行参数信息。譬如上面的例子中(./my_program fred barney betty),@ARGV数组中的元素为:$ARGV[0] = fred, $ARGV[1] = barney, $ARGV[2] = betty。程序自己的名字被存储在Perl的特殊变量$0中。

可以在程序开始后和使用钻石操作符前调整@ARGV,从而改变处理的参数(可能不是命令行参数了)。例如,下面我们可以处理三个指定的文件,不论用户在命令行中输入了什么参数:

@ARGV = qw /larry moe curly/; # 强制读取这三个文件

while (<>) {

...

}

4.向标准输出进行输出

使用print函数向标注输出进行无格式的输出,如:print "Hello, I'm here!n";

使用printf函数向标准输出进行格式化的输出,格式化操作和C语言类似,如:printf "Hello, %s. Your password expires in %d days! n", $user, $days_to_die;

格式字符串含有几个所谓的转换,每个转换以一个百分号(%)开始,以一个字母结束;在后面列表中的条目数目应该与转换的个数相同,如果它们不匹配,就很难正确工作。

%g:g表示General,要按一般较合适的方式打印一个数字,可以使用%g,它会根据需要自动选择浮点、整数,甚至是指数表示;

%d:表示十进制整数,会根据需要对数据进行截取(注意,不是舍入);类似的,%x表示十六进制,%o表示八进制;在d前面加上整数,可以表示需要打印的字段宽度,若整数为负数,则表示左对齐;

%s:表示一个字符串,它按字符串进行给定值的替换,但有一个给定的字段宽,譬如,printf "%10sn", "wilma";

%f:表示浮点数,它会根据需要进行舍入,可以指定小数点后的位数,譬如,printf "%12.3fn", 6*7 + 2/3;

%%:打印一个真正的百分号,它的特殊之处在于它不需要列表中的元素与之对应。

2007年4月29日星期日

《Learning Perl》学习笔记 -- 第五章 散列

本章讲述了散列(hash)的概念、访问方法及针对散列的一些函数

1.散列的概念

散列类似于数组,与数组相同的是它可以含有任意数目的值并随意读取它们;与数组不同的是,在散列中,使用的索引是字符串(这里成为键(key))而不是数值,即使用名字来查找对应的值。键是任意字符串,在某个确定的散列中,它的值是唯一的。

键和值(value)都是任意的标量,但键总是被转成字符串。

2.访问方法

和标量、数组一样,散列拥有独立的命名空间。

访问散列中的元素,可以使用如下的语法:

$hash{$some_key}

访问整个散列,使用百分号(%)做前缀

%hash

3.赋值

为了方便起见,可以将散列转换为一个列表,并转换回来。给散列赋值是一个列表上下文,这个表由键-值对组成:

%some_hash={"foo",35,"bar",12.4,2.5,"hello","wilma",1.72e30,"betty","byen");

在这种赋值中,不太容易分辨键和值的对应关系,在Perl中,可以使用大箭头(=>)来表示键和值的对应关系,如下所示:
%some_hash={
"foo" => 35,
"bar" => 12.4,
2.5 => "hello",
"wilma" => 1.72e30,
"betty" => "byen",
);
散列(在列表上下文中)的值是一个简单的键-值对列表:
@any_array = %some_hash;
上式称之为展开(unwind)散列,展开时不能预知键-值对的顺序,但是键和值总是对应的。

4.散列函数
4.1 keys和values函数
my @k = keys %hash; # 获得该散列中所有的键
my @v = values %hash; #获得该散列中所有的数值

在一个标量上下文中,这些函数给出散列中的元素(键-值对)个数
my $count = keys %hash;

4.2 each函数
each函数用于遍历一个散列,每次返回一个键-值对作为一个二元素列表。实际情况下,一般只在while循环中使用each,如下所示:
while ( ($key,$value) = each %hash) {
print "$key => $valuen";
}
上面这个例子用于遍历散列%hash,每次取一个键-值对,并将该键-值对赋给($key,$value)列表。当遍历完该散列时,($key,$value)=(undef,undef),此时,while循环条件不成立,则循环结束。

为了遍历散列,也可以使用foreach和keys函数相结合的方式,采用这种方式,还可以在遍历时对散列进行排序,如下所示:
foreach $key (sort keys %hash) {
...
}

4.3 exists函数
要查看某键是否在散列中,可以使用exists函数,它在键存在时返回真,不论相应的值是真还是假:
if (exists $books{"dino"}) {
...
}

4.4 delete函数
delete函数从散列中删去指定的键(和相应的值)。(如无此键,它的任务就结束了。此时既无警告,也没有错误消息。)
my $person = "betty";
delete $books{$person}; #撤销$person的借书卡

4.5 reverse操作符
使用reverse操作符可以生成一个逆散列,即原先的键变为新散列中的值,原先的值变成新散列中的键。如果原散列中的值不是唯一的(即值之间有重复),则无法判断新的散列中某个键对应的是哪个值。因此,使用reverse操作符变换散列一般只适用于键和值都是唯一(不重复)的散列。

2007年4月27日星期五

《Learning Perl》学习笔记 -- 第四章 子例程

本章讲述了子例程(subroutine)的概念,介绍了子例程的定义、调用格式、参数、返回值等。

1.子例程的概念

子例程和其它编程语言中函数的概念类似,唯一的区别是Perl中的子例程总是用户定义的,而函数可能包括系统自带的内置函数。

和标量、数组类似,子例程也有单独的命名空间,该命名空间以与字符("&")标识。

2.定义及调用格式

用关键字sub和子例程的名字定义一个子例程,如下所示:

sub max {

...

}

调用的时候,去掉sub,在子例程名字前面加"&amp;",如下所示:

$max_num = &max($a, $b);

3. 参数和返回值

传递给子例程的参数,会自动保存在子例程内的一个默认变量@_中,这是一个数组变量,对其中的元素进行访问的方式为$_[i], i=0,1,...

譬如:

sub max {

if ($_[0] > $_[1]) {

$_[0];

} else {

$_[1];

}

}

默认情况下,在子例程中得到的最后一个计算值自动成为返回值,即不需要明确的return语句。

当然,使用return语句可以立即从子例程中返回一个值,并不再执行子例程的其余部分。

4. 私有变量及严格的编码规范

使用my关键字定义的变量为私有变量,其作用范围为最小的代码块。用法如下:

my $a; #定义了一个私有标量

my ($a, $b); #定义了一个私有列表

为了告诉Perl执行严格的语法规则检查,可以把use strict pragma放在程序顶部(或在任何你希望强制使用这些规则的块或文件中)

use strict; #强制使用一些好的编程规则

5.其它

忘记local,我们用不到这个东西:P

在调用子例程时,总是使用与字符(&),这是安全和保险的。

2007年4月26日星期四

《Learning Perl》学习笔记 -- 第三章 列表和数组

本章讲述了列表和数组的概念、针对列表和数组的一些运算符和函数,并着重阐明了Perl中重要的“上下文”的概念。

1.列表和数组的概念

列表(list):是一个有序的标量集合;

数组(array):是一个包含列表的变量。

因此,简单地说,列表是数据,而数组是变量。

在Perl中不需要事先定义数组的大小,数组的大小总是可以根据需要自动扩展和收缩,没有被赋值或预定义的数组元素其值为undef。

1.1 访问数组及数组元素

对整个数组的访问很简单,在数组名前面加上@符号即表示整个数组,如@array。

使用索引访问数组元素,索引从0开始,逐渐递增,和C语言相同。

譬如数组名为array,则访问数组元素的方式为:$array[index]。

一个数组的最后一个元素的索引值为$#array(array为该数组名)。

Perl中还提供了一种从数组尾部访问数组元素的快捷方式:负的数组索引从数组的尾部算起。譬如,$array[-1]表示array数组的最后一个元素。

1.2 命名空间的概念

在Perl中,标量、数组和后面章节将要讲的散列的变量名是在不同的命名空间,你可以在同一个程序中定义一个名为Jerry的标量,名为Jerry的数组和名为Jerry的散列,而Perl不会讲它们搞混,因为它们本来就没在一个命名空间。要记住的是访问类型的变量,需要使用不同的前缀,可以认为前缀是命名空间的名字。以$开头的总是标量,以@开头的总是数组,以%开头的总是散列。

2.针对列表和数组的运算符和函数

2.1 ".."运算符

".."运算符表示一个区间,譬如1..5,表示从1到5的五个数字(1 2 3 4 5),一般用于列表或数组的赋值中。

2.2 qw快捷方式

qw表示“被括引的单词(quoted words)”,用于将一些字符序列赋值给列表或数组。

譬如要将fred, barney, betty,wilma和dino赋值给数组array,如果不用qw快捷方式,则需@array = ("fred", "barney", "betty", "wilma", "dino");这样需要键入大量的双引号。如果使用qw,则为@array = qw /fred barney betty wilma dino /;

注意qw快捷方式后面使用的分隔符是任意的,可以使用//,也可以使用!!或<>等,只要这两个匹配即可。

2.3 pop和push操作符

这两个操作符将数组当作堆栈来处理,pop用于从数组中弹出一个数据,push用于向数组中压入一个数据,针对的都是数组的尾部。

语法:$var = pop @array; push @array, $var;

2.4 shift和unshift操作符

这两个操作符的功能和pop与push类似,只是它们针对的是数组的头部进行操作。

语法:$var = shift @array; unshift @array, $var;

2.5 foreach控制结构

这个控制结构用于遍历整个数组,语法为:

foreach $var (@array) {};

要注意的是在遍历数组时,$var不是数组元素的拷贝,它就是数组元素本身,因此在{}中改变$var将改变array数组本身。但是,在遍历结束后,$var将恢复遍历数组前的值,即如果遍历数组前,$=10,则遍历完成后,$var仍然等于10。

2.6 reverse操作符

reverse操作符取一个列表的值(可以是来自一个数组),然后返回相反顺序的列表。记住reverse只是返回反序列表,它并不影响它的参数。因此,如果返回值不被赋给别的变量,它就毫无用处。

语法:@var = reverse @array;

2.7 sort操作符

sort操作符取一个列表的值(可以是来自一个数组),然后按照内部字符序进行排序。对ASCII字符串,就是按照ASCII字母表的顺序。sort和reverse相同,不影响它的参数,因此,你必须把你要的结果赋给别的变量。

3. 上下文的概念

上下文指的是一个表达式是在哪里出现的。它实际上就是一个简单的思想:一个给定的表达式在不同的地方,可能会有不同的含义。当Perl解析你的表达式时,它总是期望一个标量值或一个列表值或一个其它的值。Perl的期望就被称作表达式的上下文。对Perl中具体上下文的认识需要在实践中逐步领会。

譬如:

5 + something; # something必须是个标量

sort something; # something必须是个列表

一个有意思的现象是,当把一个数组赋值给一个标量时,这个标量获得这个数组的元素的个数,$var = @array;

有些时候需要强制使用标量上下文,这时可使用一个假函数scalar通知Perl,这里需要一个标量上下文。如scarlar @array;

在列表上下文中,从<STDIN>获得的数据存储在一个数组中,每行为一个数组元素。@lines = <STDIN>; #在列表上下文中读取标准输入

3.1 Perl的缺省变量$_

在任何需要使用标量变量的地方,都可以省略不写,而Perl会自动使用缺省变量$_表示这个变量。

譬如:

foreach (1..10) { #缺省使用$_

print "I can count to $_!n";

}

2007年4月25日星期三

《Learning Perl》学习笔记 -- 第二章 标量数据

这章介绍了Perl语言中标量数据的概念、应用于标量数据的操作符及if和while两种控制结构。

1.标量(Scalar)数据的概念
在Perl中,单个的数字和单个的字符串都被视为标量数据,而在其它一些编程语言中,字符串被视为字符数组(譬如C语言中)。
1.1 数字标量
Perl中的数字没有整型、浮点型的区别,在Perl的内部统一用浮点型表示,对于用户来说,感觉不到差别。
八进制直接量以0开头,十六进制以0x开头,二进制以0b开头。
1.2 字符串标量
字符串是字符的序列,字符串中可以包含任意字符的组合。在Perl中表示字符串有两种方式:单引号字符串和双引号字符串。字符串是放在单引号'(或双引号")之间的字符序列;单引号'(或双引号")本身并不是字符串的一部分,它们只是让Perl确定字符串的开始与结束。
1.2.1 单引号与双引号在字符串标量中的区别
在单引号间,除了单引号和反斜杠以外的任何字符在字符串中表示该字符本身;
在双引号间,则可以使用反斜杠转义字符及变量替换。
所以,若想获得纯粹的字符串,可以使用单引号;若想使用反斜杠转义字符或变量替换,则使用双引号。
1.2.2 变量替换
当把一个字符串用双引号括起来时,就要对它进行变量替换(除了要检查反斜杠转义符以外)。也就是说,字符串中的所有标量变量名都将被替换为它的当前值。
如果只有一个变量,则不必使用替换,下面两个语句的功能是相同的:
print "$var";
print $var;
1.3 数字与字符串的转换
数字转换为字符串:直接在数字上加上单引号或双引号即可,譬如把数字37变成字符串,37-->"37"。
字符串转换为数字:直接去掉单引号或双引号,并去掉非数字字符,如第一个字符不是数字,则转换后,该数字为0。譬如"37jerry"转换为数字后,变成37;"jerry"转换为数字后,变成0。
1.4 标量变量
标量变量以$开头,后跟文字(字母和数字)和下划线,但不能以数字开头。
在Perl中,变量在第一次赋值前有特别的undef值,这个值对于数字来说,相当于0;对于字符串来说,相当于空串。所以在Perl中,相当于对定义的变量已经进行了初始化,不必担心由于未初始化而出现的一些错误。

2.操作符
2.1 数值操作符
包括常规的+,-,*,/,%(求模),**(求幂)等操作符。
2.2 字符串操作符
字符串可以用.操作符连接起来。
串重复操作符x(小写字母x):这个操作符取它左边的操作数(一个字符串),生成连续的拷贝,重复次数由它右边的操作数(一个数字)决定。譬如,"fred"x2="fredfred";
2.3 二元赋值运算符
和C语言类似,Perl中有二元赋值运算符,譬如+=,*=等。
2.4 比较操作符
比较数字:<, <=, ==, >=, >, !=。
比较字符串:lt,le,eq,ge,gt,ne(含义和上面的数字比较符对应)。

3.控制结构
3.1 if控制结构
if () {};
if () {}; else {};
3.1.1 if控制结构中条件判断的真假问题(布尔值)
几条规则:
特殊值undef是假;
0是假,其它的数字全为真;
空串('')是假,其它的字符串一般是真;
一个例外:因为数字和字符串是等价的,所以0的字符串形式,'0',和它的数值形式有同样的值:假。这点是和C语言有区别的地方。
总结:标量值为undef,0,'',或'0'时,为假;所有其它的标量都为真。
3.2 while控制结构
while(){};

4.有用的函数
4.1 取得用户输入
使用行输入操作符:$line = ;
$line是自己定义的标量变量,Perl以换行符判断一个行输入的结束,同时换行符也会存储在变量$line中。
4.2 chomp操作符
chomp作用于字符串,用于去掉字符串结尾的换行符且只能去掉一个,如果该字符串末尾不是换行符,则chomp什么也不做。
chomp($line);
chomp $line; #也可以
这涉及到Perl的一个基本规则:除非去掉括号会改变意思,否则括号总是可有可无的。
4.3 defined函数
用于判断一个变量是undef还是非空字符串,可以使用defined函数,它对undef返回假,其它所有情况返回真。

2007年4月24日星期二

《Learning Perl》学习笔记 -- 第一章 简介

写在前面:
本着读书“由厚变薄,再由薄变厚”的精神,努力整理自己的思绪,将《Learning Perl》的内容浓缩、提取,写写学习笔记,便于自己以后复习,也希望对这本书的其它读者有所帮助。

这章主要介绍这本书的写作风格、Perl语言的由来、Perl的现状等,有用的信息主要包括以下几点:

1. Perl的获得:

Windows下建议使用ActivePerl,目前版本在5.8以上。这个版本的Perl有良好的安装模式,和别的windows安装程序类似。

Linux的发行版一般都预安装了Perl解释器。

2.CPAN

CPAN的全称是Comprehensive Perl Archive Network(综合Perl存档网络),里面有Perl本身的源代码、适用于各种非Unix系统的二进制安装文件、示例、文档、Perl扩展以及关于Perl的消息档案。你需要的一切关于Perl的权威的东西都来自这个网站,可以在上面找到很多好用的扩展。

网址是:www.cpan.org

3.Linux/Unix下Perl语言编程示例

每个Perl语言的开头,都是以类似

#! /usr/bin/perl

开头的,这行文字告诉系统去哪儿寻找Perl的解释器。

下面是Perl的hello world程序(设其存为hello文件)

#! /usr/bin/perl

print "Hello, world!n";

在Linux下运行该程序需使用chmod命令将其标记为可执行程序:

chmod a+x hello

4.Perl的注释是从一个井号(#)一直到行尾的内容。

正常的Perl语句以分号(;)结尾;

另外,Perl的书写格式比较自由,允许随意使用无关紧要的空白。

2007年4月23日星期一

IC设计工程师的Perl语言学习之路

1.为什么要学习Perl语言?
作为一位数字IC设计工程师,有时需要生成或处理测试数据、处理一些文本信息等,这些常规的任务当然可以用C等语言实现。但是,现在我们有了一个更好的选择,那就是Perl。Perl作为一种高级的脚本语言,对处理文本的工作进行了特殊的优化,可以使用内嵌的正则表达式实现精确的匹配,仅用少量的代码即可实现我们所需要的功能。
选择Perl的理由主要是:代码编写快速、简单、功能强大。

2.如何学习Perl语言?
Perl是个庞大的语言,可以说是包罗万象,学习起来比较困难。但我们不需要熟悉Perl语言的所有功能,只需学习Perl的一个完整有用的子集,重点集中在文本材料的处理上。至于Perl其它的知识,可以边用边学,在学习的过程中,偶然发现某个强大的功能,说不定还小惊喜一把呢,呵呵。缩小了范围以后,Perl语言的学习还是相当容易的,对于有编程基础的人来说,花个一两天的时间基本上就可以写程序了。
总结:对于有特定需求的Perl语言学习者,要学会取舍,用不到的功能、语句等尽可如过眼烟云,不必深究。

3.书籍推荐
O'REILLY出版社的《Learning Perl》是Perl语言入门的经典书籍,浅显易懂,而且主要集中在文本处理领域。2006年末的时候看过这本书,许久不用,有些生疏了,这几天打算温习一下,顺便写个读书笔记,整理一下思路,便于以后温故而知新。
这本书学完之后,如有兴趣可以看看O'REILLY出版社的《Perl Cookbook》,这本书以食谱的形式介绍了Perl语言各个领域的知识,可以有选择性的阅读、学习。

2007年4月20日星期五

Linux鼠标滚轮配置

装了Debian系统有段时间了,一直习惯于无鼠标滚轮的日子,以为Linux下本身就没法使用鼠标滚轮。虽然在看网页和文档的时候多少会有些不便,但也一直没有试图去改变。今晚舍友看我用Debian,很惊奇的发现鼠标滚轮居然没法使用,我这时也觉得Linux作为一个优秀的系统,不应该没法使用鼠标滚轮的。然后,在网上找找资料,改了下配置文件,现在鼠标滚轮可以使用了。It‘s wonderful !

修改/etc/X11/xorg.conf,主要两点:一是将Protocol改为“ImPS/2”;二是添加
Option "ZAxisMapping" "4 5",这一行的含义是将滚轮上滚动作映射为鼠标第4键,将滚轮下滚动作映射为鼠标第5键。

Section "InputDevice"
Identifier "Configured Mouse"
Driver "mouse"
Option "CorePointer"
Option "Device" "/dev/psaux"
Option "Protocol" "ImPS/2"
Option "Emulate3Buttons" "true"
Option "ZAxisMapping" "4 5"
EndSection

2007年4月19日星期四

等效逻辑门的计算

在数字IC设计中,经常会遇到等效逻辑门的概念,用来衡量设计的电路的规模。究竟什么是等效逻辑门,以及等效逻辑门是怎么计算的呢?
我们知道,综合工具(如Synopsys的Design Compiler)一般只给出面积和逻辑单元(Logic Cell)的信息,而没有等效逻辑门的信息。因为所有的逻辑电路都可以用与非门来实现,所以,通常所说的等效逻辑门实际是等效二输入与非门(NAND2)。我们可以首先使用综合工具得到同一工艺下一个NAND2的面积,然后,用综合后的电路面积除以这个NAND2的面积即可得到等效逻辑门的数值。

下面是关于集成电路规模的解释:
– 集成度,规模: 包含的晶体管数目或等效逻辑门(2输入的NAND)的数量,1个2输入的NAND=4个晶体管

2007年4月18日星期三

Linux gftp-2.0.18 -- 彻底解决中文乱码问题

Debian最新稳定版etch中的gftp,是个非常好用的图形化ftp客户端. 但是该版本在访问远程ftp中文目录或者软件时会出现乱码问题,网上的解决方案大多为修改“远程字符集”,实践证明,这种方法并不总是有效,即在某些ftp服务器上有效,而在另外一些ftp服务器上依然会出现乱码。要彻底解决gftp的中文乱码问题,需要在gftp-2.0.18版本的源码上打补丁,同时修改“远程字符集”。实践证明这种方法是有效的,介绍如下:

1、卸载系统中已安装的gftp-2.0.18(如果还没有安装,则直接进入第二步)
#apt-get --purge remove gftp
2、下载gftp-2.0.18的源码包(gftp-2.0.18.tar.bz2)及远程字符集补丁(gftp_remote_charsets.patch.gz)。
3、打补丁,编译,安装
假设上述两个包均放在/tmp文件夹中,用root账号执行下列操作:
(a)解压缩gftp源码包
#tar jxvf gftp-2.0.18.tar.bz2
得到一个文件夹:gftp-2.0.18/
(b)解压缩补丁包
#gunzip gftp_remote_charsets.patch.gz
得到gftp_remote_charsets.patch文件
(c)打补丁
#patch -p0 < remote_charsets="gbk,utf-8,gb2312,cp936" g_filename_encoding="@GBK">G_FILENAME_ENCODING. This environment variable can be set to a comma-separated list of character set names. GLib assumes that filenames are encoded in the first character set from that list rather than in UTF-8. The special token "@locale" can be used to specify the character set for the current locale.
详细解释请查看官方文档:http://developer.gnome.org/doc/API/2.4/glib/glib-running.html

2007年4月17日星期二

【转帖】终极谈判:透露一些VIA的Intel芯片组FSB授权谈判情况

历史:
Intel:要想继续获得芯片组FSB授权,必须放弃处理器产品线,可以转卖給其他公司,自拆不算数,卖给台积电和威盛集团的其他公司,如威盛通讯、广达等也不算數。
VIA:如果Intel硬逼則考慮和nVidia合作研發新x86處理器,退出Intel平臺芯片集市場。

基本协议业已达成:
VIA獲得FSB授權以及將來的CSI授權
VIA不能和nVidia合資,只能自己開發CPU和芯片集
VIA的CPU不能使用Intel未来的前端总线(CSI)架构,現有AGTL+ 前端总线可以兼容,VIA CPU不能和Intel CPU同樣物理接口。
四核筆記型CPU以及对应的全集成SoC推出時間須在2008年6月以後,雙核須在2007年12月後。
VIA不能做Intel平臺的高端桌面非整合芯片组,可以推整合芯片组,可以推全線的筆記型及低功耗芯片组。
這一次授權時限仍是5年(正在磋商中)可能VIA要考虑拆分,把處理器部門轉讓到VIA comm。

威盛CPU看来要重出江湖了

前几天看新闻的时候注意到一条消息“惠普选择威盛CPU 在华推节能型商用电脑”,当时印象颇为深刻,因为威盛的CPU在PC上已经消失很久了,这次惠普作为电脑制造领域的主流公司,采用威盛CPU,无疑是对威盛CPU的一种肯定。

威盛在收购Cyrix公司后,即开始涉足通用CPU市场,我记忆中的威盛CPU好像叫C3,后来因为和Intel的专利官司,威盛一度近乎放弃了CPU领域的研发,很少再看到威盛CPU的踪迹了。今年以来,情况似乎发生了变化,威盛频频在笔记本、超移动计算机(UMD,一种介于笔记本和PDA之间的小型电脑)等领域发力,取得了不错的成绩;公司内部的每周新闻邮件中,也多是关于威盛最新CPU C7的消息,不知道是不是意味着威盛将要把业务重心转向CPU领域。北京的研发部门似乎没有做CPU的,不过我还是希望以后能够有机会参与CPU的研发,呵呵。
威盛的芯片组业务营收占其总营收的2/3左右,但威盛与Intel的FSB授权今年4月就到期了,如果不能顺利续约,威盛今后将不能继续生产Intel平台的芯片组了,这对威盛是个巨大的打击。不知两家公司的谈判进行的怎么样了,网上很难找到确切的消息。
希望威盛一路走好!

以下是转载网上的新闻:

惠普选择威盛CPU 在华推节能型商用电脑

赛迪网讯4月13日消息我国台湾威盛技术公司周五宣布,惠普已决定采用其低价、低耗能的处理器,在中国这个蓬勃发展的新兴市场推出新的节能型商务PC。

据外电报道,惠普决定在其新推出的康柏台式机中采用Via处理器,对威盛的处理器业务来说,无疑是个巨大的胜利。

在全球处理器市场,威盛远远落后于竞争对手英特尔和AMD。据市场研究公司MercuryResearch的数据,威盛的市占率只有1%到2%。

惠普计划在精简型客户端(Thinclient)PC上采用Via处理器,这种客户端大量的计算任务往往依赖服务器来完成。选择Via,使惠普成为了第一个在主流市场采用威盛处理器的大型电脑制造商。

据悉,惠普新推出的产品型号为HP Compaq dx2020,采用威盛VIA C7-D桌面处理器,最大功耗只有20瓦。

威盛总经理陈文琦在一份声明中表示,该电脑将在降低能耗和保护环境方面为众多不同规模的中国企业提供机遇和可能,并籍此提升他们的运行管理水平。

2007年4月16日星期一

Flexlm管理的license格式介绍

许多EDA软件的加密采用Flexlm(Flexible License Manager)方法,这是由Globetrotter公司发明的软件加密方法。Globetrotter公司向软件厂商出售相关开发软件,软件厂商把此加密程序集成到自己的软件中,该方法是目前最为流行的EDA软件加密方法,已被80%以上的EDA公司所采用。该方法可以锁定机器的硬盘号、网卡号、使用日期、支持加密狗等,以保护软件的知识产权。

下面简单介绍Flexlm软件管理的license的文件格式。

License文件由注释行、Server行、Daemon行以及Feature行构成,另外使用续行符号''用来表示一行的继续。


注释行
当一行的开始是'#'符号时,该行被认为是注释行。

Server行
Server行用来标识一台特定的主机,其格式如下:
SERVER host hostid [port]
SERVER是该行的关键字,标识该行为Server行,不能更改;
host表示主机的名称,在UNIX/LINUX系统中,可以用命令“hostname”或“uname -n”获得;在Windows NT/2000/XP系统中,可以通过命令“ipconfig /all”获得;
hostid表示主机的ID号,使用Flexlm License管理工具的lmhostid命令获得;
port表示使用的TCP/IP的端口号,在UNIX/LINUX系统下,该数值需要大于1024,因为小于1024的端口号已被操作系统使用;如果没有指定port,则使用27000~27009之间的一个有效端口号。一般使用27000端口号。

Daemon(或Vendor)行
Daemon行用来标识不同的软件提供商,该行的格式如下:
DAEMON daemon_name [daemon_path]
DAEMON是该行的关键字,标识该行为Daemon行,不能更改;
daemon_name是实际运行的License管理工具的名称,如lmgrd等;
daemon_path是该工具的存放路径。

Feature行
Feature行用来对软件特定的功能进行限制,常见格式如下:
FEATURE feature vendor feat_version exp_date num_lic SIGN=sign [optional_attributes]
FEATURE是该行的关键字,表示该行为Feature行,不能更改;
feature是软件提供的特定功能的名称;
vendor表示软件提供商的名字;
feat_version表示该feature的版本号;
exp_date表示该license的过期日期,格式为dd-mm-yy,例如31-04-2007。另外,如果该字段为"permanent"或yy位为0(或者00,000,0000),那么该license永不过期;
num_lic表示该许可的终端用户个数;
SIGN=sign是用于验证该feature的签名,是根据以上条件和Flexlm加密算法计算出来的密码,一般和机器的硬件设备相关,譬如硬盘号,网卡号等;
[optional_attributes]有众多选项,详细的可参考Flexlm的End-User-Manual。

续行符号''
一行太长需要续行的时候,在行末尾用''符号表示续行。

2007年4月7日星期六

我的求职故事[原创]

2006年十一长假过后,便开始了我的求职之旅。我对自己的定位比较明确:希望找个专业对口的公司去做研发,主要是自己比较喜欢做工程类的东西,另外,也觉得如果找其它方面的工作,自己似乎没有什么优势:);另外在北京上了6年多的学,还是有些感情的,所以希望最好能在北京。按照这两条要求来找,其实没有几家公司。我是学数字集成电路设计的,全国来说,主要是北京、上海和深圳相关的公司多一些;从北京来说,规模比较大,实力比较强的公司主要有威盛电子、中星微电子、华大集成电路和海尔IC,另外,珠海炬力去年刚在北京成立了一家公司,目前还处于创业阶段,人比较少。锁定公司以后,下面就是听宣讲会、投简历、准备笔试和面试了。
海尔IC招聘的时间比较早,是我去面试的第一家公司,这家公司主要做数字电视、机顶盒等,涉及视频编解码,和我的硕士课题还比较相关,另外,该公司还在做我国自己的视频编码标准AVS的芯片设计,我觉得比较有前途,当时还是很想去这家公司的。通知面试的时间是下午2点,我早早的就到了,在等候室等着。海尔IC的面试流程安排的不好,好几组的人过来面试,它不是分组同时面试,而是一个人接着一个人的面试,结果到我面试的时候,差不多下午5点了,感觉稍微有些不爽。面试我的有三,四个人,先让我介绍自己的硕士课题,然后他们对其中的一个模块问了点问题,面试就结束了。由于是第一次面试,有点紧张,感觉自己发挥的不太好。另外,不知道公司是如何选人的,没有笔试,面试也没问什么深入的问题。不管怎么样,回到学校后,我还是给公司的HR发了封感谢信,这是在求职准备中学到的,呵呵。第二天,收到公司HR的邮件,通知我被录取了。当时心里多少有些兴奋和激动,首战告捷呀,有了个offer就不用慌了。谁知,又过了一天,又收到公司HR的邮件,告诉我前面的邮件发错了...我无语了,录取与否,原本都是正常的事情,但这样的遭遇,让我觉得自己被耍了,只好哀悼自己的第一次面试居然给了这么一家公司了:)
接下来是威盛电子。威盛的招聘流程比较正规化,先是开宣讲会,然后网上投简历,接下来是笔试、面试,而且效率很高,十天左右就全部搞定了。为了准备威盛的笔试,我拿起落满尘埃的专业书籍,前往久违的教室去上自习了。威盛的笔试题目质量还是比较高的,涉及的面也比较广,幸亏提前准备了一下,否则可能笔试都过不了,呵呵。笔试后大概两天左右,开始通知面试了。威盛的面试在清华科技园的阳光水吧举行,一共四轮,前两轮是技术面试,过了技术面试后,会去见部门的老大,老大这关过了后,就去见HR了。面试我的第一位面试官,对技术细节很关注,详细的询问我设计中他感兴趣的各个地方,问的我都有点晕头转向了,有一两个问题回答的不是很好,但是也算过了。第二位面试官比较和善一些,主要问一些基础知识及设计中大方向的一些东西,感觉自己回答的还可以。过了两轮技术面试后,下面就是去见部门老大了,这轮有两个人在主持面试,一个在宣讲会上见过,比较和善;另外一个是台湾过来的,不是那么和善,我亲眼见他把一个同学送回去了(据了),当时心想,千万别让他面试我呀。天不遂人愿,我被安排由那位不大和善的面试官面试,我尽自己的努力回答他的问题,同时始终保持着微笑。面试结束的时候,我忐忑不安的等待着,不知道他会让我回去还是让我去见HR,还好,我被送到了HR那里。在HR那边就没什么可谈的了,主要是一些例行的沟通,比如户口、待遇一类的。面试后大概一周,威盛开始发offer了,先是HR打电话通知,然后,部门经理还会给你打个电话,一是祝福,二是介绍下自己的部门,同时回答新人的一些问题,感觉还是比较人性化的。拿到威盛的offer后,基本上就决定签了。因为威盛在业界的水平不错,做芯片组、CPU、GPU及其它一些东西,产品线丰富;另外,威盛的技术实力、管理等在上面所说的那些公司中算是领先的,自己可以学到不少东西。刚毕业的时候,希望能够去家大公司,这样可以使自己的技术路线正规化。
虽然基本决定签威盛了,还是去面了其它三家公司。华大集成电路在高家园的一个小区里面,感觉不大符合我想像中的IC设计公司的形象,太生活化。到了以后,先笔试,笔试后面试,这里面的人比较和善,大家一起探讨了视频解码电路的一些东西。出来后,感觉面试还可以,第二天HR就给我打电话通知录取了,说了工资待遇一类的,让我考虑一下再给答复。炬力北京公司的老总是我导师的同学,和我们实验室以前有过合作,我到了后,先介绍我的导师,然后随便聊了几句,这位老总就说要给我offer了,相当的顺利,呵呵。中星微电子是我面试的最后一家公司,这家公司主要做摄像头芯片,现在在向其它方面拓展,已经在美国纳斯达克上市了,办公环境还是很不错的。中星微电子的面试是这样的:简历投过去以后,各个部门的经理都会看一下,如果谁感兴趣的话,就在简历上写上自己的名字,然后面试的时候就挨个过来面试。我那天总共面了六七位经理,和大部分的经理都相谈甚欢,大概是因为已经有了offer,心里没有压力,比较放得开的缘故吧。中星微电子的offer发的比较晚,面试后一周才给我offer,而在这之前两天我已经和威盛签了三方了,只好很抱歉的告诉了HR,中星微电子还是个挺不错的公司。
我的求职历程在与威盛签了三方后就落下了帷幕,从十一回校后开始找工作,到正式签三方,大概用了差不多一个半月的时间,还算比较顺利,总结一下经验教训,主要有以下几点:
首先是要明确自己的定位,想好自己打算从事的行业与职业,锁定候选公司范围,这样可以减少投简历的盲目性;
其次,要做好笔试准备,现在很多公司第一关就是笔试,如果笔试不过的话,就没有机会了;
接下来,要把以前做过的项目、自己课题的东西整理一下,面试的时候一般都会问到 ;
最后,就是准备一份精美的简历,准备去投吧

2007年4月2日星期一

我的Google blog第一贴

一直很喜欢使用Google的产品与服务:用Google查找资料、把Gmail作为主力邮箱使用、使用Gtalk和朋友联系、用docs.google写读书笔记等,可以称得上是gfan了:)我是个崇尚"简洁即是美"的人,Google产品的简洁与高效给我留下了深刻的印象。2006年我刚开始写blog的时候,Google的blog服务(blogspot.com)在国内访问不了,只好使用了别的公司提供的blog服务。最近发现blogspot.com基本上可以稳定访问了,于是赶紧申请了自己的Google blog空间,以后自己的blog要以本blog为主了,呵呵。
刚才把blogger.com的功能看了看,发现可以自定义的地方还是挺多的,这对于喜欢新鲜事物的我,无疑是件好事,又有了折腾的空间了:P不过自己在网页制作这方面没啥基础,要恶补一些知识才行,基本的HTML语法都忘得差不多了,更别提CSS等高级的玩意了。
我在百度空间已经有了一个生活blog了,打算把这个blog用作技术blog,涉及的技术主要有数字IC设计、EDA软件使用、从事的专业领域的知识以及日常开发用到的一些GNU/Linux工具,希望blog能够记录我学习的过程,见证我是如何从一个初出校门的菜鸟成长为IC设计的专业人士的(希望能够顺利成长啊:P),偶尔也会有一些业界的最新资讯;另外,会写或转载一些和自己的兴趣爱好相关的东西,譬如Open Source、家庭理财等方面。尽量多写些原创性的东西,也是个锻炼自己写作能力的方法。更新可能不会太勤,有所思则有所写、有所得亦有所记;无,则无。要把写blog当成一种享受,而不能作为一种任务:)