2009年7月15日星期三
你的C/C++基本功是否扎实?
分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。
1.找错题
试题1:
void test1()
{
char string[10];
char* str1 = "0123456789";
strcpy( string, str1 );
}
试题2:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1 = 'a';
}
strcpy( string, str1 );
}
试题3:
void test3(char* str1)
{
char string[10];
if( strlen( str1 ) <= 10 )
{
strcpy( string, str1 );
}
}
解答:
试题1字符串str1需要11个字节才能存放下(包括末尾的'\0'),而string只有10个字节的空间,strcpy会导致数组越界;
对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,
str1)调用使得从str1[url=]内存[/url]起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;
对试题3,if(strlen(str1) <= 10)应改为if(strlen(str1) <
10),因为strlen的结果未统计'\0'所占用的1个字节。
剖析:
考查对基本功的掌握:
(1)字符串以'\0'结尾;
(2)对数组越界把握的敏感度;
(3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案:
2. 编写一个标准strcpy函数
2分
void strcpy( char *strDest, char *strSrc )
{
while( (*strDest++ = * strSrc++) != '\0' );
}
4分
void strcpy( char *strDest, const char *strSrc )
//将源字符串加const,表明其为输入参数,加2分
{
while( (*strDest++ = * strSrc++) != '\0' );
}
7分
void strcpy(char *strDest, const char *strSrc)
{
//对源地址和目的地址加非0断言,加3分
assert( (strDest != NULL) && (strSrc != NULL) );
while( (*strDest++ = * strSrc++) != '\0' );
}
10分
//为了实现链式操作,将目的地址返回,加3分!
char * strcpy( char *strDest, const char *strSrc )
{
assert( (strDest != NULL) && (strSrc != NULL) );
char *address = strDest;
while( (*strDest++ = * strSrc++) != '\0' );
return address;
}
从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!
(4)对strlen的掌握,它没有包括字符串末尾的'\0'。
读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为:
int strlen( const char *str ) //输入参数const
{
assert( strt != NULL ); //断言字符串地址非0
int len;
while( (*str++) != '\0' )
{
len++;
}
return len;
}
试题4:
void GetMemory( char *p )
{
p = (char *) malloc( 100 );
}
void Test( void )
{
char *str = NULL;
GetMemory( str );
strcpy( str, "hello world" );
printf( str );
}
试题5:
char *GetMemory( void )
{
char p[] = "hello world";
return p;
}
void Test( void )
{
char *str = NULL;
str = GetMemory();
printf( str );
}
试题6:
void GetMemory( char **p, int num )
{
*p = (char *) malloc( num );
}
void Test( void )
{
char *str = NULL;
GetMemory( &str, 100 );
strcpy( str, "hello" );
printf( str );
}
试题7:
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
... //省略的其它语句
}
解答:
试题4传入中GetMemory( char *p
)函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完
char *str = NULL;
GetMemory( str );
后的str仍然为NULL;
试题5中
char p[] = "hello world";
return p;
的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。
试题6的GetMemory避免了试题4的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句
*p = (char *) malloc( num );
后未判断内存是否申请成功,应加上:
if ( *p == NULL )
{
...//进行申请内存失败处理
}
试题7存在与试题6同样的问题,在执行
char *str = (char *) malloc(100);
后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个"野"指针,应加上:
str = NULL;
试题6的Test函数中也未对malloc的内存进行释放。
剖析:
试题4~7考查面试者对内存操作的理解程度,基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确,却也绝非易事。
对内存操作的考查主要集中在:
(1)指针的理解;
(2)变量的生存期及作用范围;
(3)良好的动态内存申请和释放习惯。
再看看下面的一段程序有什么错误:
swap( int* p1,int* p2 )
{
int *p;
*p = *p1;
*p1 = *p2;
*p2 = *p;
}
在swap函数中,p是一个"野"指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误"Access
Violation"。该程序应该改为:
swap( int* p1,int* p2 )
{
int p;
p = *p1;
*p1 = *p2;
*p2 = p;
}
3.内功题
试题1:分别给出BOOL,int,float,指针变量与"零值"比较的 if
语句(假设变量名为var)
解答:
BOOL型变量:if(!var)
int型变量: if(var==0)
float型变量:
const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
指针变量: if(var==NULL)
剖析:
考查对0值判断的"内功",BOOL型变量的0判断完全可以写成if(var==0),而int型变量也可以写成if(!var),指针变量的判断也可以写成if(!var),上述写法虽然程序都能正确运行,但是未能清晰地表达程序的意思。
一般的,如果想让if判断一个变量的"真"、"假",应直接使用if(var)、if(!var),表明其为"逻辑"判断;如果用if判断一个数值型变量(short、int、long等),应该用if(var==0),表明是与0进行"数值"上的比较;而判断指针则适宜用if(var==NULL),这是一种很好的编程习惯。
浮点型变量并不精确,所以不可将float变量用"=="或"!="与数字比较,应该设法转化成">="或"<="形式。如果写成if
(x == 0.0),则判为错,得0分。
试题2:以下为Windows NT下的32位C++程序,请计算sizeof的值
void Func ( char str[100] )
{
sizeof( str ) = ?
}
void *p = malloc( 100 );
sizeof ( p ) = ?
解答:
sizeof( str ) = 4
sizeof ( p ) = 4
剖析:
Func ( char str[100]
)函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
数组名的本质如下:
(1)数组名指代一种数据结构,这种数据结构就是数组;
例如:
char str[10];
cout << sizeof(str) << endl;
输出结果为10,str指代数据结构char[10]。
(2)数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;
char str[10];
str++; //编译出错,提示str不是左值
(3)数组名作为函数形参时,沦为普通指针。
Windows NT 32位平台下,指针的长度(占用内存的大小)为4字节,故sizeof(
str ) 、sizeof ( p ) 都为4。
试题3:写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
解答:
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
MIN(*p++, b)会产生宏的副作用
剖析:
这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的"参数"也不是真的参数,在宏展开的时候对"参数"进行的是一对一的替换。
程序员对宏定义的使用要非常小心,特别要注意两个问题:
(1)谨慎地将宏定义中的"参数"和整个宏用用括弧括起来。所以,严格地讲,下述解答:
#define MIN(A,B) (A) <= (B) ? (A) : (B)
#define MIN(A,B) (A <= B ? A : B )
都应判0分;
(2)防止宏的副作用。
宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对MIN(*p++,
b)的作用结果是:
((*p++) <= (b) ? (*p++) : (*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。
除此之外,另一个应该判0分的解答是:
#define MIN(A,B) ((A) <= (B) ? (A) : (B));
这个解答在宏定义的后面加";",显示编写者对宏的概念模糊不清,只能被无情地判0分并被面试官淘汰。
补充:
#include <filename.h> 和 #include "filename.h" 有什么区别?
答:对于#include <filename.h> ,编译器从标准库路径开始搜索 filename.h
对于#include "filename.h" ,编译器从用户的工作路径开始搜索 filename.h
试题4:为什么标准头文件都有类似以下的结构?
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
豹豹:由基金排行榜及沪深300指数所想到的(二)
巴老的确不相信"市场永远有效"这种提法,但他也总是小心翼翼的等待最佳击球机会,他剔除掉了投资决策的主观性和感性因素,让"价格-价值缺口"、"价格/价值方程"来代替他决策。他认为,如果随随便便的击球,投资业绩注定不理想。为了等待一次有把握的机会,他甚至长期关注几十年才介入,这种理性和耐心,也注定不大可能再出现"下一个巴菲特"。
可是,行为金融学的兴起,倒让很多"价值投资者"自负起来了,甚至认为"市场先生经常很愚蠢",经常嘲笑市场先生。行为金融学上有一条推论:
前提:投资人是不理性的
公理:市场是无数投资人的加总
结论:因此,市场是不理性的
这种逻辑似乎很常见,但是,这恰恰是行为金融学的一个bug,市场是一个非线性的系统,不是简单的线性加总,无数投资人是不理性的,市场上存在噪音交易,而市场的多样性、互动作用起来,市场总体而言,仍有可能是很理性的、很有效率的。
我认为,真正的价值投资者,恰恰要高度重视市场先生,缜密的审视自己的投资过程,试图先将自己驳倒,先自己去"证伪",从多个角度找出自己投资分析上的漏洞,而不要轻言"市场是愚蠢的"、"市场定价错了"。
在一个复杂的适应性系统里面,会有很多悖论,如我们中学时代历史教科书上批判的"美国的西进运动",英国的"圈地运动"乃至中国隋朝的大运河,这是典型的"动机与实际情形背离",就历史的当局者而言,结局是悲惨的,而就人类长久而言,也有大功。再比如,经济学上的合成谬误、囚徒困境,也验证了非合作博弈中的"个体理性、群体非理性"。在一个多样性的、互动的世界里,静态的、线性的结论往往是很轻率的。
这个世界远不是我们想象的那么简单,也不会是太简单的逻辑。同样,市场多数时候往往是很聪明的。很多轻言市场愚蠢的投资人,往往付出了惨重的代价。当然了,这里也不是说"市场永远正确",更不是主张要搞趋势投资。这里只是讨论一种逻辑思维方式。
四、向指数学习什么?
比尔·米勒过去多年击败指数,他经常琢磨S&P500的结构及成分增减。普通基金很难战胜指数,包括我们个人投资,在单边上涨市里面,也容易败给指数。
其实呢,指数有几个典型的特征:1、代表性强
里面的成分股,多是各行业的绩优龙头股,代表性强;2、汰弱留强
指数不会因为某只股票表现好而删减它的份额,而是增加权重不足行业的股票;
3、低周转率 当然,指数是一个满仓的概念; 4、流动性好
主动投资型基金,则容易反其道而行之,认为自己能找到表现更好的股票,过度自信,周转率高,而且受人性法则及市值法则左右,股价表现过好时,往往会卖出,而烂股票则容易捂着。很多个人投资者也每每是高周转、高换手率,在保留股票方面,容易将表现好的股票卖了而保留令人失望的烂股票。
要战胜市场,最关键的就是3条:
1、恪守安全边际的法则,坚持"价值"投资
"低风险、高收益的机会,才称得上是机会";这是战胜市场的最关键。"有效的抑制亏损",是压倒一切的战略任务。
最重要的是购买"价格-价值缺口"大的廉价资产组合,而不是不管低估没有,去买一堆公认的"好股票"。
2、精选个股,坚持"集中"投资
一定要坚持相对的集中投资,在"价格-价值缺口"大、公司基本面坚实、自己最了解、风险最小的股票上,重仓出击;
3、低换手率,杜绝过度交易及波段操作,坚持长期投资
这里的"长期",只是相对的概念,价值实现及价值成长均是要时间的,像短短几天、几周时间就换股,肯定不是严肃的态度,当然了,也并不是说一定要超长期投资,这里重点是强调一种良好的交易习惯及面对市场价格波动的良好态度。对于基本面坚实、估值合理、且能持续成长的股票,是应该坚持长捂不放的。
事实上,多数人在09年想战胜沪深300指数,就有些困难,不过下半年我认为不大可能再有目前的表现了。
五、多多关注投资过程
算到现在,来到市场也2年了,一来就赶上个牛尾巴,撞上了大熊。不过,综合起来看,08、09年某些方面跟自己比还是有些许进步,具体的实证组合的performance如下:
08年 09年
mine -10.1 90
沪深300指数 -47.6 87.0
注:08年取的是加权平均的点位
由于是小资金的实证组合,可以坚持"集中投资",2年下来,居然都战胜了沪深300,但是08年仍然是亏损的,有些分析事后看比较草率。09年也只是微弱的优势战胜了沪深300。个人投资呢,其实压力比较小,而且没有仓位的限制,偶尔取得好一点的成绩并不难,甚至可以说只要坚持理性投资,个人投资组合要战胜大部分基金经理还是比较容易的。
其实这些基金经理也并不容易,在一个规则很复杂、限制较多又受短期压力制约的投资世界里,要管理大资金并取得好的成绩、坚持理性投资,真的不容易,一个在基金的兄弟也常跟我说"你不要将基金经理想象的得太简单了,哪一天你自己坐在这个位置上,你会发现不好做,要打败市场真的很难"。这真的是实情,在一个复杂的环境里管理一个受限制的大资金,并不容易。
现在值得考虑的是"投资过程",而不是目前的一点performance,很多垃圾股其实涨幅更大,这又是一轮"猪都被吹到天上跑"的行情,很多人说"撑死胆大的",这种情形,恰恰值得警惕,不要轻易的认为自己分析严谨,很可能是市场行情好、运气好造成的"偶然成功"而已,尽管从目前来看检验投资组合,我认为估值仍比较安全,承担的风险并不大,但是,现在要紧的是关注投资过程而不是短期结果。没有高质量的投资过程的话,只要重复的投资下去,是注定不可能有好的成绩的。
当然了,仅仅强调以沪深300为benchmark并不够,重要的是"不要亏损+持续战胜沪深300",要充分认识到复利的艰难、长期投资的艰难及市场先生的强大和聪慧,严密的检查投资过程的严谨性,用决策树分析模式再详细审核关键的投资思路的漏洞,多关注"价格-价值缺口"的估算的严谨性。多多关注投资过程,我们要的是长期的、必然的投资成功而不是基于运气和冒险、取巧的一时成功。
豹豹于2009年7月12日中午
豹豹:由基金排行榜及沪深300指数所想到的(一)
"熊市不亏/微亏/少亏+牛市/上涨市大赚",这是战胜市场的一个公式。努力追求绝对回报绝对没有错,但我认为,还得有一个benchmark,比如说:盈利30%好还是不好呢?这取决于环境,如果是大牛市,这个成绩可能很臭;反之,如果是极差的环境之中,这个成绩可能很惊艳。比较好的业绩基准,就是沪深300指数,它汇集了沪深两市的精华。
这次反弹以来,走出了不少表现惊艳的基金,如公募中的一些指数基金,典型的如易方达深证100ETF(159901)、融通深证100ETF(161604),偏股型基金如中邮核心优选(590001)、华夏复兴(000031);私募信托中,更有几只产品在09年的收益率达到了100%以上。
沪深300指数09年迄今的收益率是87%,全部公募基金中,能达此成绩以上的只有3只:易方达深证100ETF(159901)、中邮核心优选(590001)、华夏复兴(000031);私募信托产品,不完全统计也有3、4只的样子。在普涨的行情中,要战胜沪深300指数,的确很难很难。
如果将时间推进到2008年,将这一两年的表现串起来看,结论又有所不同,能有稳定表现的基金相当少,如果扣住"熊市少亏+牛市平均成绩"这2条标准同时符合的话,无论是公募还是私募,能做得到的基金都相当少。
不说易方达深证100ETF(159901),这是典型的大起大落型的指数基金。拿今年以来相当惊艳的中邮核心优选(590001)来看,其实检验一下完整的投资脉络,今年的惊艳并不是什么值得开心的事情。我们可以将08、09年的表现串起来看:
08年 09年
中邮核心优选(590001) -61.6 91.7
沪深300指数 -66.0 87.0
这只基金表现做到了"上涨市大赚",但并没有做得到"熊市不亏、微亏、少亏",我们知道重大的亏损对长期复利的损害是极大的。
公募基金中,真正值得注意的是华夏复兴股票(000031),将08、09年的表现串起来看:
08年 09年
华夏复兴股票(000031) -38.4 87.8
沪深300指数 -66.0 87.0
这只基金在08年亏损38.4%,尽管算不上很好,但在公募基金中很难得,而09年的表现则相当不错。这2年来的综合表现是相当优秀的。有意思的是,08年公募基金中的冠军泰达荷银成长(166201)在08年的收益率是-32.3%,是表现最好的股票型基金,但在09年的收益率只有31%,落后于沪深300不少。公募基金极少有表现稳定的,可谓"各领风骚两三年"而已。
私募信托中,09年的反弹明星,其实呢,问题也比较严重。比如说景良能量、新价值2,这2只信托均是08年成立的,单看09年的表现,相当惊人,均达到了100%以上,但是检验一下08年的表现,发现问题比较严重,2者的净值,一度达到了0.4-0.5元,亏损近半。最终算下来,这2只反弹明星的信托,1年多下来,也才赚得20%的绝对回报。
私募信托中,表现出色的当属从容投资的吕俊先生,拿他的从容优势1来看:
08年 09年
从容优势1 -4.2 55.2
沪深300指数 -55.3 87.0
(注:这里假如这只信托未在后来接收过资金,因此起点值只计算信托成立当日的沪深300指数)
吕俊先生在08年的表现相当惊人,亏损才4.2%,远远少于同期指数,今年虽然略逊于沪深300,但总体而言,远远战胜了沪深300。同样,武当投资的田荣华先生、星石投资的江晖先生也是表现出色。其实呢,"抑制重大亏损"这一条远比牛市里面多赚几十个点要重要得多、可贵得多。
一两年的净值表现还不足以说明全部问题,这里只是有感于媒体的喧嚣,说什么"反弹冠军"、"09年冠军",其实"连续的、稳定的表现"才是最重要的。
回首这次牛熊转换,有不少值得我们深入反思的问题:
一、价值投资"知易"乎?
经常听到的一种说法是"价值投资'知易'行难",价值投资真的是"知易"乎?现在很多人都标榜自己是"价值投资者"。像前几年"买入并持有"、"买入伟大公司"均被解读为价值投资,甚至被解读为价值投资的全部。很多人还说很多伟大公司的股价能涨了上千倍,可是,这种提法明显有两个隐蔽前提:1)假定自己目光如炬一定能看清未来,绝对能认定这些公司是能涨上很多倍的伟大公司,因此,无论是多高的价格买入都能赚;2)伟大公司在漫长的岁月长河中、在众多的公司中,尽管是小概率事件,而自己聪慧无比,一定能将小概率的事情找出来。
事实上,"伟大公司"事后很多年才能看得清,事前、事中的判断是很复杂的、难度很大的。看对的概率大,还是看错了的概率大?看错了怎么办呢?能不作保守估计吗?
巴老反复强调的"用40美分买1美元"、"不要亏损"、格老所强调的"全面的、严谨的分析"、"本金的安全"、"满意的回报",这些提法倒被人忽略了,卡拉曼更是一针见血的指出"一个投资人,不可能仅凭阅读一两本书就成为合格的价值投资者"。而"涨上千倍"、"伟大公司"、"投资很简单"的提法则多少反映了社会的浮躁。
我倒更相信两点:1、好的投资者,追求真理胜于追求财富本身,投资就是他们的生命,他们是基于对投资的热爱而非对财富的憧憬而喜欢投资的。追求真理是第1位的,财富、名利只是"追求真理"的副产品;2、好的投资人,是保守的投资人,他们宁愿放弃伟大的成功机会,也不会去犯致命的错误。他们的心态是超然的,更不会有狂热的想法和浪漫的幻想。他们深知市场可能犯错误,而自己可能更愚蠢。
我有一个武断的判断:价值投资是"知难行易"。真正"知"的人,行动起来其实并不难;行动起来经常出错的人,大多是自以为"知"其实并不知。
二、再谈期望值准则、概率思维与安全边际
投资是一个典型的玩概率的领域,在投资世界里,最确定的事情就是"不确定性",幻想找到物理学、工程学那样的确定性再去决策,那是不可能的。概率思维、决策树分析模式,是最起码的思维能力。
可是,这样的思维能力,很多自称是"价值投资者"的人显得很稀缺,包括宏观经济形势、需求状况、产业竞争乃至公司的产量、销量、价格、成本、现金流等很多问题,事实有多种概率,如:至少可以分成"繁荣"、"一般"、"萧条"等情况,分别进行估算。但很多人自称是"死多头"、"死空头",完全是一根筋的思考问题,看多时看得死多,完全不考虑那几个变量如果作悲观的估计会如何、预期落空了会怎么办;死空头则一根筋的看跌。
很多人只看到了巴菲特长期持有有些公司,而不去分析深层次的原因。巴老经常打桥牌来增强自己的概率感、巴老主管保险公司进行大量的概率估计,包括巴老回顾买入富国银行时,作了几种概率分析及最糟糕时的概率分析,这种概率思维的训练则没有多少人提。
在网络股时代,巴老诚实的承认"一家公司的内在价值如果在2-200亿美元的话,我完全不知道它到底是2亿美元,还是200亿美元",巴老在抛完中石油之后坦率的承认"油价在75美元每桶时,我比较中性了,尽管不是说它一定会跌",相信很多"价值投资者"们如果面对"2-200亿美元"的情况,在40亿美元乃至100亿美元市值时大多会选择买入而不是逆向思维一下"错了怎么办"。
投资世界是整个世界的一部分,投资决策是全部决策的一部分。我们并不能看清未来,更遑论"自己一定能看清未来",保持对世界、对人生的谦卑,预留误判的空间,是很有必要的。凡事只作最乐观的估计,而不去权衡各种可能性和概率,不权衡期望值,放在任何领域都不能成功,更别说在投资这个高度竞争、高度有效的市场领域之内。
记得赵丹阳先生曾提过一种提法"低风险、高收益的机会,才叫机会",这可谓抓住了投资的精髓。所谓的安全边际,其实呢,就是保证:
向上的空间大、概率大
向下的空间小、概率小
安全边际的精髓,就是保证"正期望"决策,立于不败之地,仅此而已。在一个高度依赖于概率的领域,没有这种思维能力,是很可怕的,不管在口头上标榜自己是怎样的"价值投资者"。我武断的认为:不具备概率思维、决策树分析能力的投资人,也不可能是真正的价值投资者,也难以取得长期的投资成功。
丢掉了安全边际,也就丢掉了价值投资的灵魂,正期望决策就荡然无存,就长期而言,投资迟早演化成而必败。
网络零售平台挑战沃尔玛
作者: 陈永谦 关键词: 新财富;网络;沃尔玛;零售
Alice.com商业模式最大的特点在于不依赖商品销售差价获利,并提供免费配送服务。它的出现令供应商可以绕过传统零售商直接向消费者出售产品,这可能颠覆供应商对零售商的渠道依赖。
经济危机打击奢侈品厂商的同时,也令物美价廉的网络购物更深入人心。不过,对许多消费者而言,如果算上邮寄费用,网络购物往往并不是那么节省成本。近日,一个名为Alice.com的网络购物平台在美国悄然出现,由于与快速消费品生产商携手,其商品售价不仅与沃尔玛相当,还提供免费邮寄服务。它的模式不但向亚马逊(Amazon)、drugstore.com等网络商店发起挑战,也冲击着沃尔玛、Target等传统零售业巨头。
不依赖销售差价获利的
网上零售平台
一般而言,亚马逊等网络零售商与沃尔玛等传统零售商的区别在于销售渠道,在商业模式上则区别不大,均作为中间环节,先向供货商采购,再销售给终端客户,其盈利主要来自于供销差价的通道费。Alice.com的商业模式则完全不同,其最大的特点在于,把自己定位于为快速消费品生产厂商提供一个交易平台,而不依赖商品销售差价获利,同时为消费者提供免费配送服务。
从供应商方面看,Alice.com向家用快速消费品生产厂商开放平台,加入Alice.com平台的厂商可以为自己的产品定价,并按此价格通过网站进行销售。由于免除了中间环节,Alice.com标榜每件商品都以沃尔玛的价格作为标准,其同类商品价格能比网上竞争对手便宜20-30%。Alice.com独特的模式得到不少世界消费产品生产巨头的青睐,由于它专注于销售厕纸、洗洁精、牙膏、垃圾袋、洗衣粉、尿布等家用快速消费品,在试业期间,宝洁、强生、高露洁等相关领域厂商就为它提供了6000种不同的商品。
从消费者方面看,Alice.com同样贯彻免费策略,在Alice.com上所有的订购邮寄服务都是免费的,买家订购的商品会装在一个印有Alice标识的盒子里,通过其合作伙伴UPS寄给美国各地的消费者。由于邮寄免费,对Alice网站而言,只出售一种产品显然成本过高,因此它规定用户必须购买6种以上的商品才能完成一笔交易。在试业阶段,用户的每笔交易大约购买11种商品,平均花费为50美元。
Alice.com还负责客户服务。消费者可以在它的网站上创建一个关于自己家庭状况的文件夹,其中包括有多少家庭成员、孩子等个人资料。网站会根据文件夹中的记录追踪消费者购买的商品,并在商品将要用完时通过email提醒买家继续订购。在Alice.com的CEO布赖恩·韦根(Brian
Wiegand)和他的创业同伴马克·麦奎尔(Mark
McGuire)的设计中,这也将是网站未来的盈利点之一:网站可以通过出售消费者购买行为的数据分析等产品,从厂商那里获得一定回报。
Alice.com计划的另一个盈利点主要通过向供应商收取广告费,从而为消费者提供优惠券、客户忠诚计划等活动来实现。很多厂商每年都需花费数十亿美元为旗下产品做传统广告,但效果并不明显,Alice认为,优惠券和客户忠诚计划等另类广告,不仅能使消费者直接受益,也能让厂家直接面对目标客户,以更低的成本取得更明显的推广效果。
在这方面,韦根和他的同伴已经积累了一些经验。他们2005年创办的购物搜索网站Jellyfish的盈利模式与此相似,如果买家通过Jellyfish的搜索结果向某一零售商订购产品,Jellyfish就会把零售商提供的广告费用和买家分享,向买家提供约4-5%的现金折扣。2008年,他们将Jellyfish出售给了微软。
不过目前来看,Alice.com的盈利前景仍然模糊,但如果它能取得成功,将对传统的零售模式带来颠覆性的冲击,供应商与零售商之间的关系将会重构,整个零售行业都可能面临一次新的洗牌,而Alice.com的推出也正是利用了供应商希望摆脱零售商控制的心理。
受益消费品厂商与
零售商的博弈
在传统的百货零售业,一般都是几家巨头控制着绝对的市场份额。全球最大的零售连锁企业沃尔玛2008年在美国的销售额就达到了4056亿美元,相当于全美所有百货公司之和。凭借渠道和规模优势带来的议价能力,沃尔玛能提供最具竞争力的商品价格,从而不断打压竞争对手的市场份额。在金融危机的背景下,通过低价手段进行竞争的优势会更加明显,最新数据显示,沃尔玛在美国零售市场的份额从2008年的10%逐渐上升到目前的11.3%。在零售巨头拥有渠道优势的情况下,大多数供应商都没有太强的议价能力,就连宝洁等行业巨擘也不得不接受零售巨头们压价的要求。
在经济衰退的背景下,很多零售巨头也开始采取更加积极的策略推进自有品牌的销售,最近,美国第二大零售商Target又推出了自有品牌的洗洁精,并以更低的价格与其他供应商的商品直接竞争。这种行为使许多厂商感到不满,但他们不得不面对的现实是,自己的产品大部分都要通过这些零售商销售出去。
正如零售商不断推出自有品牌产品一样,供应商也希望能直接面向消费者销售产品。在电子商务时代,很多高附加值的品牌如耐克(Nike)都通过公司网站直接向消费者提供产品;而在牙膏牙刷之类的低品牌附加值、低利润行业,还没有厂商直接拥有自己的网上商店,因而,在与零售商的博弈中,他们更处下风。这也正是Alice.com定位于家用快速消费品销售的重要原因。
就在消费品厂商在零售巨头自有品牌的威胁和金融危机的影响下希望寻找新的销售途径时,适时出现的Alice.com迎合了他们的需求。通过这个平台,厂商可以拉近与消费者的距离,并减少对零售商的依赖。因此,一些牙膏和洗洁精厂商甚至不惜开罪大型零售商也愿意支持Alice.com。在某种程度上,Alice.com提升了供应商在与零售商进行利益分配谈判中的地位,这无疑有助于这个新型购物平台得到越来越多供应商的支持。不过正如消费品牌专家肯·哈里斯(Ken
Harris)所指出的,Alice.com的成功取决于品牌厂商持续加盟的情况。
陈玮:PE青睐什么样的创业团队
作者: 陈玮 关键词: 新财富;PE;创业
在10年接触超过4000家企业、投资超过100家企业后,我们发现,同时具有三种特质的创业者取得成功的可能性更大,也更容易受到PE的青睐。除了一些共同的特质,不同模式的企业,对团队核心能力的要求也存在一些差异,企业成功的关键还在于团队特质与企业模式相匹配。
PE界有一句十分流行的话,投资只有三个标准:第一是人,第二是人,第三还是人。投资就是投人,投团队。但什么样的团队更受到PE的青睐,却是见仁见智,从来没有统一的标准。千里马常有,伯乐不常有,这也是中国本土PE的现实写照,在投资界要找到怀抱资金、面带微笑的天使太难,而在芸芸众生中要找到可以托付的创业者也不容易。投资的时候,PE们最看重,却也是最看不透的,就是企业的管理团队。即使你是穷尽天下相书,拜访名山相师,也无法练就一双火眼金睛。如何判断一个团队是否值得投资,是PE们最花心思的地方。
投资要投三种人
总结过往的投资案例,成功的创业团队往往存在很多共性,如要具备勤奋好学、艰苦奋斗、创业精神等素质。在10年中接触超过4000家企业、投资超过100家企业后,我们发现,同时具有三种特质的创业者取得成功的可能性更大,也更容易受到PE的青睐。
一是大气的人,胸怀宽广。胸怀有多广决定了事业有多大,大气的人往往凝聚力强,能团结一批人才在自己的周围,从而能更好地成就自己的事业。投资者喜欢管理团队在一起工作过3至5年以上,而且管理团队不断有新的人员加入,创始人能把10-20%的股份分给核心管理层。柳传志在联想初创期,为了留住技术骨干、核心人员,将最好的住房、最好的车子让给他们,以其不争,得成其业。任正非在华为内部实行期权制,将股权分散到团队中,自己持有的股权最后只有4%。大气,这是企业家精神重要的组成部分。
在考察企业时,投资人往往会关注公司股权中有无核心管理团队持股。创业者如果把股权都看成自己的,不愿意跟自己的团队分享,团队的稳定性和前景也会具有不确定性。我们遇到过这样的案例。初创的互联网企业,发起人是一个80后工作狂,狂热地投入自己的事业,并以此带动核心团队一起向前冲,企业发展迅速。在投资调查时,我们问发起人今后对创业团队的股权安排,他回答说,不用,我们都是志同道合的一帮人,真心喜欢这个事,不要钱他们也跟着我干。我们回答,不要钱也跟着干,在现阶段当然好,反映了团队的凝聚力、事业心,但正是因为你有这样一支热情、专业、贡献的团队,才更应该考虑他们的股权,保持团队长久的战斗力。一个成功企业家成为团队的精神领袖,必因他不吝与队友分享共同的商业成果;在和队友共同艰苦奋斗的同时,更应为他们规划出光明的未来。所幸,这位创业者非常聪明且具有长远眼光,在我们的协助下,企业建立了一套综合考虑长短期发展的股权激励机制。投资这样的团队,投资者更有信心。
看创业者是否大气,除了股权,还要看治理结构。曾经有一个投资项目,在进行调查时,一个情况引起我们极大的兴趣。这是一个传统行业的家族式企业,有多年的运营历史,各个关键岗位由家族人员担任,企业快速发展壮大。后来,他们从外部聘请了一位财务总监,这位财务总监是一位性格直率的专业人士,从自身业务的角度,提出许多不同于以往公司运营惯例的看法。公司老板非常开明,一一听取并逐步落实,且有意识地开始淡化家族管理特色,引入外部血液。投资者们对这种变动趋势抱欣赏的态度,增强了投资信心。这家企业通过引入投资者,真正建立了三会一层(股东会、董事会、监事会、管理层)的公司治理机制。通过一年的运营,公司老板深有感触地告诉我们,有了外部投资者,重大决策比以前程序多,麻烦了,但是,公司犯大错误的概率也降低了。创业者有广阔的胸怀,能听取不同的声音,而又坚持自己的理念,这才是可以让投资者安心牵手的人。
二是一根筋的人,执著专注。根据中国中小企业协会的统计,国内中小企业的平均寿命是2.9年。而放眼世界500强,寿命在50年以上企业的又能有多少,百年老店就更难了。PE最怕创业团队花心,今天做这个,明天想那个,缺乏专注和专业性,容易受外界的诱惑。在复杂多变的环境下,每家企业都一直面临生存压力,因此,不执著专注,企业很难有长远发展。马云的阿里巴巴、陈天桥的盛大、马化腾的腾讯,在创业初期都不顺利,多次面临生死困境、举步维艰,马化腾甚至曾有出售腾讯的计划。但因为他们执著,坚持,最终还是取得了成功。
有这样一个现象,以企业上市为划分阶段,在成立5年内上市的,其第一次融资时商业计划书所描述的公司主要产品或服务,往往没有大的变化,如江南春的分众传媒。在企业成立5-10年后完成上市的,其首次融资商业计划书所描述的主要产品或服务,距离企业在上市招股书所描述,往往有了变化。这说明,市场千变万化,一流的团队随着市场变化会不断适应、调整自己的产品、市场策略,从而取得成功。
除了执著还要专注,专注于自己的行业,经得起诱惑。一些企业家在房产市场热的时候去买地盖房,矿产资源热的时候去买矿开矿,也有一些企业家过多地参加各种社会活动,热衷于担任很多社会职务,成为社会活动家。对这样的团队,投资者一般都会比较小心。PE不会投资给名片有折页的创业者,为什么?企业太多了,兼职太多了,操心太多、职务一页都写不下,投资者如何能放心。
三是好面子的人,责任天下。所谓好面子就是爱惜自己的声誉,维护自己的声誉,要有责任感,注重自己的品牌和声誉。特别是作任何决策时都要有"做老板的责任",审慎、不轻率,表里如一,言行一致,确定的目标努力去达到,不轻言放弃。我们接触过这样的创业者,在税收、社保以及经营上完全按照法律规范来做,与某些偏执于追逐利润的企业形成鲜明的对照。问其理由,创业者的答复很简单,自己的命运要掌握在自己的手中,一旦破坏了声誉,后面的成本会更大,修补也更难。
也有这样的管理团队,吸引投资的时候在业绩上对投资者的承诺很多,一旦不能实现,就以各种理由来搪塞,结果失去投资人信任,不愉快分手,后面也很难再融到资金。也有管理团队在业绩不能达到目标的时候,如实向投资人分析原因,并提出解决的办法,不仅得到投资人的谅解,也得到其后续支持。巨人史玉柱,在脑白金再次成功后,安排偿还以前巨人大厦所欠债务,这种责任感不仅重新赢得了社会的尊重,也为其确立了信誉,为其在网络游戏行业的发展提供了很好的品牌支持,得到各路投资商的鼎力支持也在意料之中。
模式与团队的匹配
PE界流行一个段子:我们说经验是非常重要的,谷歌(Google)的拉里·佩奇(Larry
Page)、谢尔盖·布林(Sergey
Brin)和百度的李彦宏笑了;我们说背景是相当重要的,阿里巴巴的马云和盛大的陈天桥笑了;我们说技术是很重要的,分众传媒的江南春和蒙牛股份的牛根生也笑了。这说明,由于新经济模式和互联网的出现,传统创业团队所需的资本、技术和经验受到了挑战,创业者的特质与行业结合成为新的创业基础。除了一些共同的特质,不同模式的企业,其团队的特质也存在一些差异,企业成功的关键还在于团队特质与企业模式相匹配。
对于消费连锁等服务业而言,团队的特点往往是专业背景不重要,从业经历比较丰富,并且往往有跨行业的经验,对社会资源要求也不高。但这类企业往往对内部管理、对团队的勤奋程度要求高。结合其盈利模式看,虽然模式上表现出来的特点是可复制和快速扩张的能力,但这种扩张的能力建立在其内部严格而精细的管理上。可以说,管理水平决定了这类模式的成败,其发展的核心在于内部管理水平。因此,对于这类企业,看管理团队,关键在于看其对所从事业务的理解、内部管理的能力,看内部管理流程是否规范,看其是否具有严格细致的工作作风。很难想象,没有严格管理的企业会在这个领域取得成功。
对网络游戏、电子商务等新互联网企业而言,支持其商业模式的关键点在于快速反应能力和执行能力。没有速度,很难生存,互联网的发展速度也是互联网企业生存所需要的速度。因此,网络企业团队的特点是年轻朝气,充满激情,富有理想,非常勤奋,效率高,执著甚至是偏执,投入甚至是狂热。在他们的企业里,加班是正常的,不加班的情况反而少见。但与此同时,这样的团队往往管理随意、沟通能力上存在不足,并且从业经历比较简单,更多的是靠商业感觉。这是互联网企业团队的一个共同点,也是网络人的特质。因此,看网络团队,关键在于内部是否构建有一个积极向上、富有感染力的企业文化,是否有一种分享的股权结构。如果互联网企业也像传统企业一样,朝九晚五,按部就班,缺乏创业激情,相信其也很难做得很成功。这种行业是年轻人的天下,如果团队平均年龄过大,即便经验丰富,相信投资人也会再三掂量。
对于技术型的制造业来说,团队成员往往在行业内有比较丰富的经历,专业背景深厚,内部管理也比较规范。一般人理解中,技术型企业技术是核心,但投资人和技术专家对技术的理解是不同的。PE们经常会碰到一些技术型的企业,对技术非常执著,甚至有完美主义倾向,产品不断试验和改进,技术不断改进,不到自己觉得完美了,不投入市场。还有一些企业对专利着迷,专利不断,但应用很少。对于投资人而言,"技术≠专利≠市场≠利润"。因此,看这种技术型的团队,不仅看其技术背景,更看其对市场的判断和了解,看其市场上的资源,看其团队上的均衡。只有技术的团队是不全面的,只有技术和市场的结合,才能顺应市场,引领市场的团队才会更容易成功。
商业模式不同,背后隐含的对团队核心能力的要求也不同。很难想象互联网的团队管理一个传统企业会做得很好;同理,也很难想象一个制造业的团队能做好一个互联网企业。不同特点的团队只有跟其所在领域的要求相匹配,才会是有成功潜力的团队。
美国第一家风险投资公司美国研究发展公司(American Research
Development)的创建者杜洛特将军(General Georges
Doriot)说过:"我更倾向于一流的创业团队有二流的想法,而不是一个二流的创业团队有一个一流的想法。"可以说,管理团队对一个企业的成败具有决定性的影响。如何能更好地判断团队,以上的看法也只是一家之言。看人,识人,没有公式,没有指标。也许这是PE所谓投资艺术的所在,也是PE行业的魅力所在。
简单的投资方法就是最好的方法
对于理性投资,精神态度比技巧更重要。
这是格雷厄姆在《聪明投资者》一书中开篇的两句话。我认为,第一句话说明,当大家都把注意力放在大盘蓝筹股上,我们应该怎么做?当中国股市处于上市公司吸钱的场所时我们怎么做?当很多人短线投机时我们怎么做?第二句话说明,格雷厄姆的投资方法非常简单,但知易行难,即使你掌握了方法技巧,但没修炼成价值投资的精神态度,你一样赚不到钱。
格雷厄姆这套简单的投资方法归纳起来共六个字:品质、估值、操作。具体如下:
一、品质――具备什么品质的股票才值得投资
应该说,格雷厄姆对股票的品质要求不是很高,巴菲特甚至把格雷厄姆式的股票称为"雪茄烟蒂"。总体来说,格老对目标股票的品质要求如下:
(一)外部特征要求:总体的思路是"规模优势、行业主导地位与股票的廉价程度成反比"。格老提出了以下可供选择的股票,但需大家自己揣摸:一是规模方面
占有压倒性优势、行业内主导地位的龙头股;二是前景明朗、成长把握大的成长股;三是行业排名靠前比较廉价的重要股;四是非常廉价的其他股。
(二)财务安全要求:主要指标至少有两个:资产负债率在50%以下;速动比率在1以上。尤其是后者,格老认为,财务的安全性主要由支付能力决定。同时,
格老对资产的确定性考察非常重视,他认为,工商界购买企业跟金融界购买股票对资产认识的分歧,是股市风险的主要来源。所以,只有保证资产是真实可靠并能客
观计算的,才能得出财务是否安全的结论。
(三)管理层要求:格雷厄姆对管理层的要求来自于一个商业原理,即允许其他人用你的钱的条件是:你能理解和非常谨慎地控制他的行动,或者你能异常坚定无保留地相信他的能力。
根据这个原理,股东关注的关于管理层的两个根本性问题是:
1、外部股东的利益是否得到合适的认可;2、管理层是否有效率。简单来说就是诚信和能力。
管理层的诚信如何评价,格老没有明白叙述,但大概可从三方面来看:一是看红利分配的持续性;二是看信息公开的真实性和及时性;三是看过去有无劣迹。
管理层的能力格老倒是提出了三条明确标准:一是在经济繁荣时期,有没有连续几年给股东以满意的回报;二是销售的边际利润能否达到整个行业的边际利润;三是每股收益的增长能否达到整个行业的增长水平。
二、估值――对好品质的股票进行精益求精的估值
安全边际理论,这是格雷厄姆投资的核心理论,其实也是价值投资的核心理论。虽然估值的方法各不相同,但目的只有一个:寻找安全边际。
格雷厄姆的估值方法如下:
1、保证数据的可靠性。为
此,从正常经营结果中分离出非正常发生的利润和亏损是非常重要的,非正常项目主要有以下几种:(1)固定资产出售;(2)证券出售;(3)到期资本发生的
折价或溢价;(4)人寿保险政策的收入;(5)退税及其利息(或相反);(6)诉讼成功或失败;(7)库存资产帐面价值的暂时减少;(8)应收账款帐面价
值的暂时减少;(9)持续的非经营性财产成本。
2、用市盈率来估算企业的价值。这个市盈率跟股票行情表的那个市盈率不同的地方是:A、股票的收益是未来7年的平均收益,不是过去的,更不是现在的。但是其预测基础是过去的真实数据;B、中立市盈率为12、最大值为20、最小值为8。
3、用资产对估值进行调整。A、当资产总额(扣除无形资产)少于估值时,对超过2倍的量减少1/4;B、当净流动资产(流动资产净额扣除流动负债)高于估值时,将估值调高50%。
4、安全边际设定为33%。即最后估算价值低于市价1/3时是安全的。泡沫边际(负安全边际)自行设定。
格雷厄姆对股票估值特别提请注意以下一些事项:
1、定量分析必须辅以定性的考虑。只有在得到对企业的定性调查结果的支持的前提下(我理解是具有第一部分所列的品质),量化的指标才是有用的。
2、当期收益不应成为评估的主要根据,相反会成为理性投资者利用的机会。
3、平均收益与收益趋势:趋势可能靠不住,趋势缺乏计算尺度。不要相信有利的趋势将一往无前,也不要认定坏的趋势无可救药,态度谨慎的分析和调查是必须的。
4、赤字是一个定性而不是定量因素。如果一个平均值包含若干个赤字年,则其指示性值得怀疑。对萧条年份和繁荣年份分段考察,会是有益的补充。
5、直觉不能成为分析家的一种常规武器。对未来的分析应言之有理,不能凭空猜测。
6、巨额利润往往只是昙花一现。竞争和工艺的变化是时刻存在的威胁。
7、每一个决定收入的因素都必须得到深入的考察,以发现未来可能发生不处变化的迹象。
三、操作――以良好的心态遵守操作纪律
对真正的价值投资者来说,大道至简,"便宜时买,贵的时候卖",这就是全部的操作手法了。事实上,格老也没有提出完整的操作手法,我根据书中的相关内容总结了以下几条,但在实践中可能还得回归到那句话:运用之妙,存乎一心。
(一)充分了解投资对象。"了解证券的价值要象了解你制造或经营的商品一样"。舍弃财务安全而取收益得不偿失。只要股票本身品质不良,即使价格值得投资也不应该给予考虑。
(二)购入股票时坚定地执行"安全边际"原则。只有根据可靠的计算表明公司很有可能产生相当好的收益的时候,才采取行动。远离很少收益和很大损失的冒险。要以萧条期作为考察公司的基础,这意味着需将正常时期的安全边际进一步提高。"负安全边际"也可用在卖出的决定中。
(三)投资应被视为一种组合性操作,风险分散措施是获得令人满意的平均结果的保证。这条跟巴菲特的相对集中投资并不矛盾,巴菲特一般也是持有二十种不同行业的股票。
(四)利用你的知识、经验和勇气。如果你已经从事实中得出一个结论,并且你知道你的判断是正确的,那就按照它行动,即使其他人有怀疑或不同意见。
2009年7月14日星期二
UNIX 高手的另外 10 个习惯
Michael Stutz 的优秀文章"UNIX 高手的 10 个习惯"的基础上,本文将提供另外 10
个 UNIX 命令行命令、工具和技术,可以使您成为更高效的 UNIX 命令行高手。
您应当采纳的其他 10 个好习惯包括:
使用文件名自动完成功能 (file name completion)。
使用历史扩展。
重用以前的参数。
使用 pushd 和 popd 管理目录导航。
查找大型文件。
不使用编辑器创建临时文件。
使用 curl 命令行实用工具。
最有效地利用正则表达式。
确定当前用户。
使用 awk 处理数据。
1. 使用文件名完成
如
果不需要在命令提示符处键入长的、令人费解的文件名,这是不是很棒呢?的确,您不需要这样做。相反,您可以配置最流行的
UNIX Shell 以使用文件名完成。该功能在各个 Shell
中的工作方式略有不同,因此我将向您展示如何在最流行的 Shell
中使用文件名完成。文件名完成使您可以更快地输入并避免错误。懒惰?也许吧。效率更高?当然!
我正在运行哪种 Shell?
如果您不知道目前使用的是哪一种 Shell,会怎么样?虽然这个诀窍不是另外 10
个好习惯的正式组成部分,但它仍然很有用。如清单 1 所示,您可以使用 echo $0
或 ps -p $$ 命令显示您正在使用的 Shell。对于我来说,运行的是 Bash Shell。
清单 1. 确定您的 Shell
$ echo $0
-bash
$ ps -p $$
PID TTY TIME CMD
6344 ttys000 0:00.02 –bash
C Shell
C Shell 支持最直接文件名完成功能。设置 filec
变量可启用该功能。(您可以使用命令 set
filec。)在您开始键入文件名后,可以按 Esc 键,Shell
将完成文件名,或完成尽可能多的部分。例如,假设您拥有名为 file1、file2 和
file3 的文件。如果您键入 f,然后按 Esc 键,将填充 file,而您必须键入 1、2
或 3 来完成相应的文件名。
Bash
Bash Shell 也提供了文件名完成,但使用 Tab 键代替 Esc 键。您在 Bash Shell
中不需要设置任何选项即可启用文件名完成,该选项是缺省设置的。Bash
还实现了其他功能。键入文件名的一部分后,按 Tab
键,如果有多个文件满足您的请求,并且您需要添加文本以选择其中一个文件,那么您可以多按
Tab 键两次,以显示与您目前键入的内容相匹配的文件的列表。使用之前名为
file1、file2 和 file3 的文件示例,首先键入 f。当您按一次 Tab 键时,Bash
完成 file;再按一次 Tab 键时,将展开列表 file1 file2 file3。
Korn Shell
对于 Korn Shell 用户,文件名完成取决于 EDITOR 变量的值。如果 EDITOR 设置为
vi,那么您键入部分名称,然后按 Esc 键,后跟反斜杠 (\) 字符。如果 EDITOR
设置为 emacs,那么您键入部分名称,然后按两次 Esc 键以完成文件名。
2. 使用历史扩展
如果您为一系列命令使用相同的文件名,会发生什么情况?当然,有一种快捷方式可以快速获得您上次使用的文件名。如清单
2 所示,!$ 命令返回前一个命令使用的文件名。从文件
this-is-a-long-lunch-menu-file.txt 中搜索单词 pickles
的出现位置。搜索结束后,使用 vi 命令来编辑
this-is-a-long-lunch-menu-file.txt
文件,而不需要重新键入文件名。您使用感叹号 (!)
来访问历史,然后使用美元符号 ($)
返回前一命令的最后字段。如果您反复用到长文件名,那么这是一个非常好的工具。
清单 2. 使用 !$ 获得前一个命令使用的文件名
$ grep pickles this-is-a-long-lunch-menu-file.txt
pastrami on rye with pickles and onions
$ vi !$
3. 重用以前的参数
!$
命令返回某个命令使用的上一个文件名参数。但如果某个命令使用多个文件名,而您只希望重用其中一个文件名,该如何做?!:1
操作符返回某个命令使用的第一个文件名。清单 3
中的示例显示可以如何将此操作符与 !$
运算符组合使用。在第一个命令中,将一个文件重新命名为更有意义的名称,但为了保持原始文件名可用,创建了一个符号链接。重新命名文件
kxp12.c 以提高可读性,然后使用 link
命令来创建到原始文件名的符号链接,以防在其他位置使用该文件名。!$
操作符返回 file_system_access.c 文件名,而 !:1 操作符返回 kxp12.c
文件名,该文件名是上个命令的第一个文件名。
清单 3. 组合使用 !$ 和 !:1
$ mv kxp12.c file_system_access.c
$ ln –s !$ !:1
4. 使用 pushd 和 popd 管理目录导航
UNIX 支持各种目录导航工具。我最喜欢的两款提高工作效率的工具是 pushd 和
popd。您当然了解 cd
命令用于更改您的当前目录。如果您要在多个目录中导航,但希望能够快速返回某个位置,该如何做?pushd
和 popd 命令创建一个虚拟目录堆栈,pushd
命令用来更改您的当前目录并将其存储在堆栈中,而 popd
命令用来从堆栈的顶部移除目录并使您返回该位置。您可以使用 dirs
命令来显示当前目录堆栈,而不会压入或弹出新目录。清单 4 显示如何使用 pushd
和 popd 命令在目录树中快速导航。
清单 4. 使用 pushd 和 popd 在目录树中导航
$ pushd .
~ ~
$ pushd /etc
/etc ~ ~
$ pushd /var
/var /etc ~ ~
$ pushd /usr/local/bin
/usr/local/bin /var /etc ~ ~
$ dirs
/usr/local/bin /var /etc ~ ~
$ popd
/var /etc ~ ~
$ popd
/etc ~ ~
$ popd
~ ~
$ popd
pushd 和 popd 命令还支持使用参数处理目录堆栈。使用 +n 或 -n 参数,其中 n
是一个数字,您可以向左或向右移动堆栈,如清单 5 所示。
清单 5. 旋转目录堆栈
$ dirs
/usr/local/bin /var /etc ~ ~
$ pushd +1
/var /etc ~ ~ /usr/local/bin
$ pushd -1
~ /usr/local/bin /var /etc ~
5. 查找大型文件
是否需要找出您的所有空闲磁盘空间被什么占用了?您可以使用以下几个工具来管理您的存储设备。如清单
6 所示,df 命令为您显示每个可用卷上已使用的块的总数,以及空闲空间的百分比。
清单 6. 确定卷的使用情况
$ df
Filesystem 512-blocks Used Available
Capacity Mounted on
/dev/disk0s2 311909984 267275264 44122720
86% /
devfs 224 224 0
100% /dev
fdesc 2 2 0
100% /dev
map -hosts 0 0 0
100% /net
map auto_home 0 0 0
100% /home
是否希望查找大型文件?使用 find 命令时附带 -size 参数。清单 7
显示了如何使用 find 命令来查找大于 10MB 的文件。请注意,-size 参数以 KB
为单位计量大小。
清单 7. 查找大于 10MB 的所有文件
$ find / -size +10000k –xdev –exec ls –lh {}\;
6. 不使用编辑器创建临时文件
以下是一个简单示例:您需要快速创建一个简单临时文件,但不希望启动您的编辑器。使用带有
> 文件重定向操作符的 cat 命令。如清单 8 所示,使用不带文件名的 cat
命令只回显向标准输入键入的任何内容;>
重定向将该输入捕获到指定的文件中。请注意,您在结束键入时必须提供文件结束字符,通常为
Ctrl-D。
清单 8. 快速创建临时文件
$ cat > my_temp_file.txt
This is my temp file text
^D
$ cat my_temp_file.txt
This is my temp file text
需要执行相同操作,但是附加到现有文件而不是创建新文件。如清单 9 所示,改用
>> 操作符。>> 文件重定向操作符向现有文件附加内容。
清单 9.快速向文件附加内容
$ cat >> my_temp_file.txt
More text
^D
$ cat my_temp_file.txt
This is my temp file text
More text
7. 使用 curl 命令行实用工具
我是否可以从命令行访问 Web?你疯了吗?没有,这就是 curl 的用途!curl
命令使您可以使用 HTTP、HTTPS、FTP、FTPS、Gopher、DICT、TELNET、LDAP 或
FILE 协议从服务器检索数据。如清单 10 所示,我可以使用 curl
命令从美国国家气象局了解我所在位置(纽约州布法罗市)的当前天气状况。当与
grep 命令组合使用时,我可以检索布法罗市的天气状况。使用 -s
命令行选项来禁止 curl 处理输出。
清单 10. 使用 curl 检索当前天气状况
$ curl –s http://www.srh.noaa.gov/data/ALY/RWRALY | grep BUFFALO
BUFFALO MOSUNNY 43 22 43 NE13 30.10R
如清单 11 所示,您也可以使用 curl 命令来下载 HTTP 托管的文件。使用 -o
参数来指定保存输出的位置。
清单 11. 使用 curl 下载 HTTP 承载的文件
$ curl -o archive.tar http://www.somesite.com/archive.tar
这实际上只是您使用 curl 命令可以完成的操作的提示。您只需在命令提示符处键入
man curl 显示 curl 命令的完整使用信息,就可以开始了解更多内容。
8. 最有效地利用正则表达式
大量 UNIX 命令使用正则表达式作为参数。从技术角度而言,正则表达式
是表示某种模式的字符串(也就是说,由字母、数字和符号组成的字符序列),用于定义零或更长的字符串。正则表达式使用元字符(例如,星号
[*] 和问号
[?])来匹配其他字符串的部分或全部内容。正则表达式不一定包含通配符,但通配符可以使正则表达式在搜索模式和处理文件时发挥更大的作用。表
1 显示了一些基本正则表达式序列。
表 1. 正则表达式序列序列 说明
脱字符 (^) 匹配出现在行首的表达式,例如 ^A
美元符号 ($) 匹配出现在行末的表达式,例如 A$
反斜杠 (\) 取消下一个字符的特殊含义,例如 \^
方括号 ([]) 匹配括起来的任一字符,例如 [aeiou](使用连字符 [-]
表示范围,例如 [0-9])。
[^ ] 匹配除括起来字符以外的任一字符,例如 [^0-9]
句点 (.) 匹配除行尾之外的任意单个字符
星号 (*) 匹配零个或多个前驱字符或表达式
\{x,y\} 匹配出现过 x 到 y 个和前面相同的内容
\{x\} 精确匹配出现过 x 个和前面相同的内容
\{x,\} 匹配出现过 x 个或更多和前面相同的内容
清单 12 显示了与 grep 命令一起使用的一些基本正则表达式。
清单 12. 使用正则表达式和 grep
$ # Lists your mail
$ grep '^From: ' /usr/mail/$USER
$ # Any line with at least one letter
$ grep '[a-zA-Z]' search-file.txt
$ # Anything not a letter or number
$ grep '[^a-zA-Z0-9] search-file.txt
$ # Find phone numbers in the form 999-9999
$ grep '[0-9]\{3\}-[0-9]\{4\}' search-file.txt
$ # Find lines with exactly one character
$ grep '^.$' search-file.txt
$ # Find any line that starts with a period "."
$ grep '^\.' search-file.txt
$ # Find lines that start with a "." and 2 lowercase letters
$ grep '^\.[a-z][a-z]' search-file.txt
有大量书籍专门讲述正则表达式。有关命令行正则表达式的深入描述,建议您阅读
developerWorks 文章"对话 UNIX,第 9 部分:正则表达式。"
9. 确定当前用户
有时,您可能希望确定某个特定用户是否运行过您的管理脚本。为找出答案,您可以使用
whoami 命令来返回当前用户的名称。清单 13 显示了独自运行的 whoami
命令;清单 14 显示了使用 whoami 确保当前用户不是根用户的 Bash 脚本的摘录。
清单 13. 从命令行使用 whoami
$ whoami
John
清单 14. 在脚本中使用 whoami
if [ $(whoami) = "root" ]
then
echo "You cannot run this script as root."
exit 1
fi
10. 使用 awk 处理数据
awk 命令似乎始终处在 Perl
的阴影下,但它对于简单、基于命令行的数据处理来说是一个快速、实用的工具。清单
15 显示了如何开始使用 awk 命令。若要获取文件中每行文本的长度,请使用
length() 函数。若要查看字符串 ing 是否出现在文件文本中,请使用 index()
函数,该函数返回 ing
首次出现的位置,这样您就可以使用它来进行进一步的字符串处理。若要
tokenize(也就是说,将一行拆分为单词长度的片段)某个字符串,请使用 split()
函数。
清单 15. 基本 awk 处理
$ cat text
testing the awk command
$ awk '{ i = length($0); print i }' text
23
$ awk '{ i = index($0,"ing"); print i}' text
5
$ awk 'BEGIN { i = 1 } { n = split($0,a," "); while (i <= n) {print a[i];
i++;} }' text
testing
the
awk
command
打印文本文件中的指定字段是一项简单的 awk 任务。在清单 16 中,sales
文件包含每个销售人员的姓名,后跟每月销售数字。您可以使用 awk
命令来快速获得每个月的销售总额。缺省情况下,awk
将每个以逗号分隔的值视为不同的字段。您使用 $n 操作符来访问每个字段。
清单 16. 使用 awk 对数据进行汇总
$cat sales
Gene,12,23,7
Dawn,10,25,15
Renee,15,13,18
David,8,21,17
$ awk -F, '{print $1,$2+$3+$4}' sales
Gene 42
Dawn 50
Renee 46
David 46
awk 命令可以很复杂并应用于广泛的情景中。若要更完整地学习 awk
命令,请从命令 man awk 开始,并参阅参考资料部分提供的资源。
结束语
成为命令行高手需要进行一些实践。按照相同的方式处理问题很简单,因为您已经习惯了。扩展您的命令行资源可以显著提高您的工作效率,并促使您朝着
UNIX 命令行高手的方向前进!
