Bash Shell 里的各种括号

作者:会写代码的猪 发布时间:October 17, 2011 分类:猪在写代码

今天在 SegmentFault 上看到又有人问起关于Shell里各种括号的问题。对于很多玩Shell的人,括号是个很尴尬的问题,用起来没问题,说起来不明白,我在这里总结一下Bash Shell几种括号的用法和区别,别的Shell我不会。。。

(( )) :一对圆括号有两个地方用到。

1,for循环,

for (( expr1 ; expr2 ; expr3 )) 

这里一对双括号里边的表达式,GNU的文档指出,expr1支持 Shell Arithmetic;expr2不为0时,expr3被赋值且语句执行。说的很麻烦,还要花时间搞清楚什么是Shell Arithmetic。其实一言以蔽之,支持数字条件。比如:

for (( a=0 ; a<10 ; a++ )); do echo $a; done

会输出 0 1 2 3 (带换行哦~~~)

2,数学表达

(( )) 和 $(( ))

(( )) 的用法与let一样,就不用多解释了吧~~~

$(( ))就是把计算结果拿出来,可以用在双引号里边,比如:

echo "1+2=$(( 1 + 2 ))"

会输出 1+2=3

( ):一个圆括号

在for循环里,跟C语法一样一样的。

或者是子程序,返回整个里边表达的返回值。里边的变量都是局部的,修改不会带到外边。举例子

a=1

(a=3; echo $a)

echo a

结果是 3 1

还有个就是圈数组。。。这个就没神马意思了

[ ]:一个方括号,是bash的命令,查man手册是可以查到的,跟test一样,在手册里可以看到很多用法。比如-b -c -gt -eq 什么的很多,还有用-a表示与,-o表示或等等

[[ ]]:一对方括号是一个方括号的加强版,则是Shell的保留字,里边支持了 || && 等等这些符号。一般我喜欢用这个

还有相对复杂的 { }

几个用处,区分变量,如:

var=abcd; echo ${var}EFG;

这样,Bash就不会认为变量是varEFG了

还有用来截取字符串的 ${ }语法比较灵活多变,这里不做多解释,大家有兴趣可以自己去搜搜资料,一般我脚本用到的字符串处理,这个都能搞定了。

代码块。用来区分代码的,但是跟( )有个区别,就是在末尾要加上 ;

目前看到常用的用法也就是这样,肯定不全,欢迎补充,欢迎交流。

iOS sqlite控件 Sqlight

作者:会写代码的猪 发布时间:September 30, 2011 分类:猪在写代码,果粉+G粉

记:上一篇文章介绍了Kache这个缓存控件,可以用来配合这次iCloud升级,这篇是关于一个sqlite的封装,Sqlight,一个很轻量级的封装,也是为了配合iCloud。模仿了PHP mysql扩展PDO的一些做法。把数据库操作封装成方法,通过NSDictionary和NSArray传递参数。源码:http://jiajun.org/g/Sqlight.zip

Sqlight真是没什么可介绍的,主要的常用方法有4个,select, update, insert和delete,还有一个create table在初始化时调用。用法示例在 Sqlite.h 文件的注释中。

简单介绍一下原理,Sqlight的数据文件是放在Documentation目录的,也就是说会被备份到iCloud。跟cache不同,我建议在数据库里存放一些比如,用户信息,登录状态等等。

以下把用法示例贴一下:

 

SqlightAdapter *sqlight = [[Sqlight alloc] initWithDatabase:@"test_database" AndTable:@"test_tb"];

if (nil == sqlight) {

sqlight = [[Sqlight alloc] initWithDatabase:@"test_database"];

 

[sqlight createTable:@"test_tb" Info:[NSArray arrayWithObjects:@"f1", @"f2", nil]];

sqlight.tableName = @"test_tb";

}

[sqlight insertData:[NSDictionary dictionaryWithObjectsAndKeys:

@"value1", @"f1",

@"value2", @"f2",

nil]];

// this is a wrong condition, there is no f0 field.

sqlight_result_t res = [sqlight selectFields:[NSArray arrayWithObjects:@"f1, f2", nil]

ByCondition:@"f0=?"

  Bind:[NSArray arrayWithObjects:@"value1", nil]]; 

NSLog(@"%d -- %@ -- %@", res.code, res.msg, res.data); // will out put 1 -- no such column: f0 -- ()

res = [sqlight selectFields:[NSArray arrayWithObjects:@"f1, f2", nil]

ByCondition:@"f1=?"

Bind:[NSArray arrayWithObjects:@"value1", nil]]; 

NSLog(@"%d -- %@", res.code, res.data); // will out put 101 -- ( value1, value2 )

[sqlight updateData:[NSDictionary dictionaryWithObjectsAndKeys:@"value_new", @"f1", nil]

ByCondition:@"f1=?"

  Bind:[NSArray arrayWithObjects:@"value1", nil]];

res = [sqlight selectFields:[NSArray arrayWithObjects:@"f1, f2", nil]

ByCondition:@"f1=?"

Bind:[NSArray arrayWithObjects:@"value1", nil]]; 

NSLog(@"%d -- %@", res.code, res.data); // will out put 101 -- ()

 

iOS缓存控件 Kache

作者:会写代码的猪 发布时间:September 30, 2011 分类:猪在写代码,果粉+G粉

记:昨天(Sep. 29)想必很多 iOS 开发者都收到Apple的邮件和苹果中国的工作人员的电话了,要求开发者升级应用,调整本地文件的存储位置,以适应即将发布在iOS5中启用的iCloud同步应用数据功能。恰好我这里有n久以前写的一个缓存控件(Kache的源码:http://jiajun.org/g/Kache.zip,现在再拿出来,希望在这次大规模的升级中,能给大家带来方便。

Kache 的基本思路是:用一个单例对象hold住整块内存,每次set都把数据set到这块内存里,get也从这里拿。在需要持久化的时候,例如程序退出之类的,调用一个saveToStorage方法,把这块内存持久化,存到iCloud文档中提到的Caches目录,这个目录是不会被iCloud备份的。在需要从本地存储载入时调用一个loadFromStorage方法,把整块内存load出来,照常使用。注意:Kache只能缓存 NSData, NSDictionary, NSArray, NSString等这些基本数据结构,不能缓存其他对象。

Kache提供两个基本功能:

1,普通缓存,允许设定有效时长,如果用户不指定被缓存数据的有效时长,则默认为86400秒,也就是一天过期。

2,缓存队列,Kache提供一个队列,用户可指定队列长度,默认为100,当新数据进入缓存队列导致队列长度超过100时,最先进入的数据会被删除。普通缓存不影响队列。

特殊需求:

之前提到,Kache使用的是一个单利hold住整块内存,那么一个单例中只允许有一个缓存队列。如果需要多个缓存队列,那么可以使用Kache提供的实例方法,开发者自己创建单例对象来hold住不同的内存。

基本用法:

用法非常简单,只要 #import "KCH.h"后,就可以按照 KCH.h 文件注释的例子来调用缓存了。

阅读源码:

Kache的源码非常简单,只有6个文件加1个KCH.h。

KCH.h基本上是一个README作用的文件。

KCHObject.h/KCHObject.m 定义了缓存的原子对象,这里记录了某个数据的过期时间和具体数据等内容。

KCHHolder.h/KCHHolder.m 定义了整个缓存的基本操作方法,包括对过期的处理,对队列的处理,持久化,重置等等。

Kache.h/Kache.m 是对KCHHolder的封装,提供了所有操作的实例/静态方法,以及对一直说到的单例的定义。

最后,是Kache的源码:http://jiajun.org/g/Kache.zip

使用Three20

作者:会写代码的猪 发布时间:June 18, 2011 分类:猪在写代码

记:Three20(简称:TT)是Facebook维护的一个开源iPhone应用框架。框架封装了一系列视觉控件,网络组件,和工具方法。最近使用TT重构了一个app,这个app在1万行规模使用的是原生代码,架构非常简单。增长到2万行规模,这个原生的架构已经疲于应付迅速变化的业务需求,因此我们采用TT进行了重构。这里,简单介绍一下使用TT开发的app采用了怎样的架构,以及开发过程中的经验和教训。

app基于TTTableViewController的架构进行设计,主要分为三层:ViewControlelr,DataSource和Model。另外,平行于这三层设有Service和Util,封装一些通用逻辑和工具,例如:登陆,URLEncode等。最底层是Manager,封装网络控件,缓存控制等。除了这些还有独立封装的组件和对系统组件的扩展,如SegmentedControll,滚动图片等。这个架构不做赘述,说一说在这个架构下遇到的几个问题,以及解决方案。

1、TT对系统控件的封装无法满足个性化需求。

TT对很多系统控件进行封装,拿之前提到过的TTTableViewController举例,所有的cell都被封装,对框架使用者透明,而TT封装的cell类型无法完全满足需求,我们往往需要格式更加丰富的cell样式。

在这种情况下,我们选择对TT方法进行重写。Objective-c提供指定类指定方法的重写,因此集中把需要个性定制的TT控件进行重写,完全不修改TT本身的代码。这样操作,既满足了需求,又使在日后对TT框架进行升级变的非常方便,几乎不需要考虑升级造成的不兼容。

2、Cell的默认操作过分单一

TT是使用Navigator和ULR的策略(欲了解该策略请参考TT官方网站http://three20.info)来管理整个应用的ViewController的。

在TableView中没一个cell带有URL,这个URL表明了点击cell后要跳转到的viewController,同时TT还认为如果一个cell没有URL那么他就是不可点击的,而往往存在这样的需求,cell可点击,但点击操作却不是跳转到某个ViewController。

针对这种情况,我们定义空URL,空URL不指向任意ViewController的类,而是指向nil。带有空URL的cell既可点击,又不会跳转到任意ViewController。

3、构造ViewController的URL不支持中文

之前说了,TT使用URL管理ViewController。有些ViewController的参数是中文,而且需要通过URL传递,而Navigator不支持汉字URL。

增加URLEncode方法,对每一个配置到URL中的参数编码,生成编码后的URL就可以正常使用。另外,TT会自动Decode的URL,无需开发者处理。

但TT的在URL策略中“/”无法使用,即使进行Encode之后,放入URL仍无法使用。这就需要开发者在构造URL过程中,检查每一个参数,确保不出现“/”。

4、稳定版TT(v1.0.5)不支持ios3.1及以下版

根据我们对客户端使用ios版本的统计,3.1及以下版的用户仍然占一定比例,还不能放弃支持。因此,考虑到支持3.1及以下版本的ios设备,需要使用v1.1 TT进行开发。

开发过程中遇到的问题很多,以上是比较明显的几个,接下来聊一聊开发经验。

1、一个界面一个ViewController

在一个应用中,ViewController往往通过简单的配置就可以复用,可以控制多个界面,但我建议ViewController不复用。复用ViewController必然导致在类中出现用于区分不同界面的逻辑,如果界面上的逻辑稍有变动,这个被复用的Controller要跟着修改,随着发展,代码会越来越复杂,因此,保证一个界面一个ViewController。

对于那些确实可以复用的逻辑,可以采用继承的方式。把可以的复用逻辑封装在一个类中,每一个直接控制界面的ViewController继承自这个父类,针对各自的个性逻辑重写相应的方法。

2、不过分使用URL

之前我们提到多次通过URL控制ViewController,Controller中的参数也可以通过URL传进去,但过度使用URL构造Controller可能会埋下隐患。URL不仅是初始化的时候使用,在运行过程中可能还需要使用这个URL在池中取出该对象。如果在URL中定义了多个参数,在获取对象的过程中,必须拿到这些参数值才能准确定位到相应对象,往往这些参数都不是全局的,所以这个过程就会非常麻烦。

因此,在某些非终端的类中,尽量不使用URL构造对象,需要传递的参数使用ApplyQuery的方式,使用一个字典构造Query,使用URLAction构造对象。

3、封装两个网络控件,带缓存/不带缓存。

TT封装的网络控件叫TTURLRequest,在TTURLRequest中允许使用缓存,默认缓存1天。在应用中,有些请求要求实时性,不允许使用缓存,尤其是一些写操作的请求。

应用本身也要对TTURLRequest进行一层封装,就是之前提到过的Manager,在NetworkManager中封装两个方法,使用缓存/不缓存。

4、使用延迟加载操作

所谓延迟操作,指的是在某个界面上加载某个组件的时候,如果直接调用addSubview方法可能会出现加载失败等诡异问题。是由于iPhone渲染一个界面需要时间,加载自己的组件需要在渲染界面之后,而调用viewLoad,甚至是viewDidLoad方法在TT框架下不能保证在渲染完成之后。因此在加载个人组件时,可能需要延迟加载,即,延迟0.3或0.5秒后再加载。TT框架本身也采用了许多延迟加载,使用[NSTimer scheduledTimerWithTimeInterval:(NSTimeInterval) invocation:<#(NSInvocation *)#> repeats:<#(BOOL)#>]方法。

 

以上介绍了8个经验和教训,希望能对大家在使用TT进行开发过程中提供一些帮助,少走弯路。

【译】Emiller Nginx模块开发指南(第二部分)

作者:会写代码的猪 发布时间:October 6, 2010 分类:猪在写代码,全说中国话

由于格式问题,这篇文章看起来可能会不太舒服,可以直接阅读我的google doc:

中文版       中英对照版

2. Components of an Nginx Module

2. nginx模块的各个组件

 

As I said, you have a lot of flexibility when it comes to making an Nginx module. This section will describe the parts that are almost always present. It's intended as a guide for understanding a module, and a reference for when you think you're ready to start writing a module.

正如我所说的,开发一个nginx模块的时候,具有非常非常强的灵活性。这部分就介绍一下这些东西。类似于理解模块的一个指南或者是你觉得你已经准备好开始开发模块的时候的一个参考资料。(译注:这一部分是最重要的,而且在日后的开发中,这部分可以当作字典来用)

 

2.1. Module Configuration Struct(s)

2.1. 模块配置结构

阅读剩余部分...

  1. 1
  2. 2
  3. 3
  4. 4