find 命令的两种用法比较

我们经常会对find出来的文件做一些处理,这时有三种方法可以选择:

1.  直接把find的结果作为命令的参数

cmd ·find ….·

这样做看起来很简单,但是最大的缺点就是经常会出现参数太长的错误,因为find出来的文件太多了,所以我们可以参考第二种方法

2. 使用-exec 参数

find ….  -exec cmd {} \;

注意:} 和 \ 之间是至少有一个空格的; 且‘;’一定是要用\做转义的
这样做find就会把find到的文件一个一个地传给cmd来执行,如果cmd只能一个文件一个文嘉地处理,这样做是很好的,但是一般来讲处理文件的命令都不是这么单纯的,都可以一次处理多个文件,而我们却非要一个一个地提供参数就显得效率低下了,下面看第三种写法

3.  使用xargs命令

find … | xargs cmd

这样xargs会在让cmd不出现参数太长的前提下,一次提供给cmd更多的参数,这就比用exec效率高了

[color=#FF0000]注意:用find命令时,正则匹配一定要用引号,比如:find / -name ‘a*’ 查找a打头的文件,如果没有引号(单双都行)的话,*将扩展为当前目录下的所有文件名或目录名

awk 中文手册

awk 命令
用途
在文件中查找与模式匹配的行,然后在它们上面执行特定的操作。
语法
awk [ -F Ere ] [ -v Assignment ] … { -f ProgramFile | ‘Program’ } [ [ File …
| Assignment … ] ] …
描述
awk 命令利用一组用户提供的指令来将一组文件和用户提供的扩展正则表达式比较,一次一行。然后在任何与扩展正则表达式匹配的行上执行操作。awk
处理的最大记录大小为 10KB。
awk 命令的模式搜索比 grep 命令的搜索更常用,且它允许用户在输入文本行上执行多个操作。awk
命令编程语言不需要编译,并允许用户使用变量、数字函数、字符串函数和逻辑运算符。
awk 命令受到 LANG、LC_ALL、LC_COLLATE、LC_CTYPE、LC_MESSAGES、LC_NUMERIC、NLSPATH 和 PATH
环境变量的影响。
本章中包括以下主题:
awk 命令的输入
awk 命令的输出
通过记录和字段的文件处理
awk 命令编程语言
   模式
   操作
   变量
   特殊变量
标志
示例
awk 命令的输入
awk 命令采取两种类型的输入:输入文本文件和程序指令。
输入文本文件
搜索和操作在输入文本文件上执行。文件如下指定:
在命令行指定 File 变量。
修改特殊变量 ARGV 和 ARGC。
在缺省 File 变量的情况下提供标准输入。
如果用 File 变量指定多个文件,则文件以指定的顺序处理。
程序指令
用户提供的指令控制 awk 命令的操作。这些指令来自命令行的‘Program’变量或来自用 -f 标志和 ProgramFile
变量一起指定的文件。如果指定多个程序文件,这些文件以指定的顺序串联,且使用指令的生成的顺序。
awk 命令的输出
awk 命令从输入文本文件中的数据产生三种类型的输出:
选定的数据可以打印至标准输出,此输出完全同于输入文件。
输入文件的选定部分可以更改。
选定数据可以更改并可打印至标准输出,此输出可以同于或不同于输入文件的内容。
可以在同一个文件上执行所有三种类型的输出。awk 命令是别的编程语言允许用户重定向输出。
通过记录和字段的文件处理
文件以下列方式处理:
awk 命令扫描它的指令,并执行任何指定为在读取输入前发生的操作。
awk 编程语言中的 BEGIN 语句允许用于指定在读取第一个记录前要执行的一组指令。这对于初始化特殊变量特别有用。
从输入文件读取一个记录。
记录是由记录分隔符隔开的一组数据。记录分隔符的缺省值是换行字符,它使文件中的每一行成为一个单独的记录。记录分隔符可以通过设置 RS 特殊变量来更改。
记录是相对于 awk 命令的指令指定的每种模式比较。
命令指令可以指定应比较记录内的特定字段。缺省情况下,字段由空白区(空格或跳格)隔开。每个字段由一个字段变量表示。记录中的第一个字段指定为 $1
变量,第二个字段指定为 $2 变量,以此类推。整个记录指定为 $0 变量。字段分隔符可以通过在命令行使用 -F 标志或通过设置 FS 特殊变量来更改。FS
特殊变量可以设置为下列值:空格、单个字符或扩展正则表达式。
如果一个记录与一个模式相匹配,则任何与该模式相关的操作都在该记录上执行。
在记录和每个模式比较且执行了所有指定操作以后,从输入读取下一个记录;在从输入文件读取所有的记录之前,该进程重复。
如果已经指定了多个输入文件,则下一个文件打开,且在读取所有的输入文件之前,该进程重复。
在读取了最后一个文件中的最后一个记录后,awk 命令执行任何指定为在输入处理后发生的指令。
awk 编程语言中的 END 语句允许用户指定在读取最后一个记录后要执行的操作。这对于发送有关 awk 命令完成了什么工作的消息特别有用。
awk 命令编程语言
awk 命令编程语言由以下格式的语句构成:
Pattern { Action }
如果一个记录与指定模式相匹配,或包含与该模式匹配的字段,则执行相关的操作。可以指定没有操作的模式,这种情况下,包含该模式的整行写至标准输出。为每个输入记录执行指定的没有模式的操作。
模式
在 awk 命令语言语法中使用四种类型的模式:
正则表达式
关系表达式
模式的组合
BEGIN 和 END 模式
正则表达式
awk 命令使用的扩展正则表达式类似于 grep 或 egrep 命令使用的表达式。扩展正则表达式的最简单的形式就是包括在斜杠中的一串字符。例如,假定一个名为
testfile 的文件具有以下内容:
smawley, andy
smiley, allen
smith, alan
smithern, harry
smithhern, anne
smitters, alexis
输入以下一行命令:
awk ‘/smi/’ testfile
将把包含 smi 字符串的具体值的所有记录打印至标准输出。在这个示例中,awk 命令的程序 ‘/smi/’ 是一个没有操作的模式。输出是:
smiley, allen
smith, alan
smithern, harry
smithhern, anne
smitters, alexis
以下特殊字符用于形成扩展正则表达式:
     字符功能
     +指定如果一个或多个字符或扩展正则表达式的具体值(在 +(加号)前)在这个字符串中,则字符串匹配。命令行:
awk ‘/smith+ern/’ testfile
     将包含字符 smit,后跟一个或多个 h 字符,并以字符 ern 结束的字符串的任何记录打印至标准输出。此示例中的输出是:
smithern, harry
smithhern, anne

     ?指定如果零个或一个字符或扩展正则表达式的具体值(在 ?(问号)之前)在字符串中,则字符串匹配。命令行:
awk ‘/smith?/’ testfile
     将包含字符 smit,后跟零个或一个 h 字符的实例的所有记录打印至标准输出。此示例中的输出是:
smith, alan
smithern, harry
smithhern, anne
smitters, alexis

     |指定如果以 |(垂直线)隔开的字符串的任何一个在字符串中,则字符串匹配。命令行:
awk ‘/allen
|
alan /’ testfile
     将包含字符串 allen 或 alan 的所有记录打印至标准输出。此示例中的输出是:
smiley, allen
smith, alan

     ( )在正则表达式中将字符串组合在一起。命令行:
awk ‘/a(ll)?(nn)?e/’ testfile
     将具有字符串 ae 或 alle 或 anne 或 allnne 的所有记录打印至标准输出。此示例中的输出是:
smiley, allen
smithhern, anne

     {m}指定如果正好有 m 个模式的具体值位于字符串中,则字符串匹配。命令行:
awk ‘/l{2}/’ testfile
     打印至标准输出
smiley, allen

     {m,}指定如果至少 m 个模式的具体值在字符串中,则字符串匹配。命令行:
awk ‘/t{2,}/’ testfile
     打印至标准输出:
smitters, alexis

     {m, n}指定如果 m 和 n 之间(包含的 m 和 n)个模式的具体值在字符串中(其中m <= n),则字符串匹配。命令行:
awk ‘/er{1, 2}/’ testfile
     打印至标准输出:
smithern, harry
smithern, anne
smitters, alexis

     [String]指定正则表达式与方括号内 String 变量指定的任何字符匹配。命令行:
awk ‘/sm[a-h]/’ testfile
     将具有 sm 后跟以字母顺序从 a 到 h 排列的任何字符的所有记录打印至标准输出。此示例的输出是:
smawley, andy

     [^ String]在 [ ](方括号)和在指定字符串开头的 ^ (插入记号) 指明正则表达式与方括号内的任何字符不匹配。这样,命令行:
awk ‘/sm[^a-h]/’ testfile
     打印至标准输出:
smiley, allen
smith, alan
smithern, harry
smithhern, anne
smitters, alexis

     ~,!~表示指定变量与正则表达式匹配(代字号)或不匹配(代字号、感叹号)的条件语句。命令行:
awk ‘$1 ~ /n/’ testfile
     将第一个字段包含字符 n 的所有记录打印至标准输出:
smithern, harry
smithhern, anne

     ^指定字段或记录的开头。命令行:
awk ‘$2 ~ /^h/’ testfile
     将把字符 h 作为第二个字段的第一个字符的所有记录打印至标准输出。此示例中的输出是:
smithern, harry

     $指定字段或记录的末尾。命令行:
awk ‘$2 ~ /y$/’ testfile
     将把字符 y 作为第二个字段的最后一个字符的所有记录打印至标准输出。此示例中的输出是:
smawley, andy
smithern, harry

     .(句号)表示除了在空白末尾的终端换行字符以外的任何一个字符。命令行:
awk ‘/a..e/’ testfile
     将具有以两个字符隔开的字符 a 和 e 的所有记录打印至标准输出。此示例中的输出是:
smawley, andy
smiley, allen
smithhern, anne

     *(星号)表示零个或更多的任意字符。命令行:
awk ‘/a.*e/’ testfile
     将具有以零个或更多字符隔开的字符 a 和 e 打印至标准输出。此示例中的输出是:
smawley, andy
smiley, allen
smithhern, anne
smitters, alexis

     \ (反斜杠)转义字符。当位于在扩展正则表达式中具有特殊含义的任何字符之前时,转义字符除去该字符的任何特殊含义。例如,命令行:
/a\/\//
     将与模式 a //
     匹配,因为反斜杠否定斜杠作为正则表达式定界符的通常含义。要将反斜杠本身指定为字符,则使用双反斜杠。有关反斜杠及其使用的更多信息,请参阅以下关于转义序列的内容。

识别的转义序列
awk 命令识别大多数用于 C 语言约定中的转义序列,以及 awk 命令本身用作特殊字符的几个转义序列。转义序列是:
     转义序列表示的字符
     \”\”(双引号)
     \//(斜杠)字符
     \ddd其编码由 1、2 或 3 位八进制整数表示的字符,其中 d 表示一个八进制数位
     \\\ (反斜杠) 字符
     \a警告字符
     \b退格字符
     \f换页字符
     \n换行字符(请参阅以下的注)
     \r回车字符
     \t跳格字符
     \v垂直跳格

注:除了在 gsub、match、split 和 sub
内置函数中,扩展正则表达式的匹配都基于输入记录。记录分隔符字符(缺省情况下为换行字符)不能嵌套在表达式中,且没与记录分隔符字符匹配的表达式。如果记录分隔符不是换行字符,则可与换行字符匹配。在指定的四个内置函数中,匹配基于文本字符串,且任何字符(包含记录分隔符)可以嵌套在模式中,这样模式与适当的字符相匹配。然而,用
awk 命令进行的所有正则表达式匹配中,在模式使用一个或多个 NULL(空)字符将生成未定以的结果。
关系表达式
关系运算符 <(小于)、>(大于)、<=(小于或等于)、>=(大于或等于)、= =(等于)和 !=(不等于)可用来形成模式。例如,模式:
$1 < $4
将与第一个字段小于第四个字段的记录匹配。关系运算符还和字符串值一起使用。例如:
$1 =! “q”
将与第一个字段不是 q 的所有记录匹配。字符串值还可以根据校对值匹配。例如:
$1 >= “d”
将与第一个字段以字符 a、b、c 或 d 开头的所有记录匹配。如果未给出其它信息,则字段变量作为字符串值比较。
模式的组合
可以使用三种选项组合模式:
范围由两种以 ,(逗号)隔开的模式指定。操作在每个以匹配第一个模式的记录开始的每个记录上执行,并通过匹配第二个模式的记录(包含此记录)继续。例如:
/begin/,/end/
与包含字符串 begin 的记录以及该记录和包含字符串 end 之间的所有记录(包含包括字符串 end 的记录)匹配。
括号 ( ) 将模式组合在一起。
布尔运算符 ||(或)&&(和)以及 !(不)将模式组合成如果它们求值为真则匹配,否则不匹配的表达式。例如,模式:
$1 == “al” && $2 == “123”
与第一个字段是 al 且第二个字段是 123 的记录匹配。
BEGIN 和 END 模式
用 BEGIN 模式指定的操作在读取任何输入之前执行。用 END 模式指定的操作在读取了所有输入后执行。允许多个 BEGIN 和 END
模式,并以指定的顺序处理它们。在程序语句中 END 模式可以在 BEGIN 模式之前。如果程序仅由 BEGIN 语句构成,则执行操作且不读取输入。如果程序仅由
END 语句构成,则在任何操作执行前读取所有输入。
操作
有多种类型的操作语句:
操作语句
内置函数
用户定义的函数
条件语句
输出操作
操作语句
操作语句括在 { } (花括号) 中。如果语句指定为没有模式,则它们在每个记录上执行。在括号里可以指定多个操作,但操作间必须以换行字符或
;(分号),且语句以它们出现的顺序处理。操作语句包含:
     算术语句
     算术运算符 +(加号), – (减号), / (除号), ^ (幂), * (乘号), % (系数)用于格式:
表达式 运算符 表达式
     这样语句为:
$2 = $1 ^ 3
     将第一个升为三次方的字段的值指定给第二个字段。
     一元语句
     一元 -(减号)和一元 +(加号)如在 C 编程语言中操作:
+Expression 或 -Expression

     增量和减量语句
     增量前语句和减量前语句如在 C 编程语言中操作:
++Variable 或 –Variable
     增量后语句和减量后语句如在 C 编程语言中操作:
Variable++ 或 Variable–

     赋值语句
     赋值运算符 +=(加)、-=(减)、/=(除)和 *=(乘)如在 C 编程语言中操作,格式为:
Variable += Expression
Variable -= Expression
Variable /= Expression
Variable *= Expression
     例如,语句:
$1 *= $2
     将字段变量 $1 乘以字段变量 $2,然后将新值指定给 $1。
     赋值运算符 ^=(幂)和 %=(系数)具有以下格式:
Variable1^=Expression1
     和
Variable2%=Expression2
     并且它们等同于 C 编程语言语句:
Variable1=pow(Variable1, Expression1)
     和
Variable2=fmod(Variable2, Expression2)
     其中 pow 是 pow 子例程而 fmod 是 fmod 子例程。
     字符串串联语句
     字符串值可以通过紧挨着陈述来串联。例如:
$3 = $1 $2
     将字段变量 $1 和 $2 中的字符串的串联指定给字段变量 $3。

内置函数
awk 命令语言使用算术函数、字符串函数和一般函数。如果打算编写一个文件,且稍后在同一个程序里读取它,则 close 子例程语句是必需的。
算术函数
以下算术函数执行与 C 语言中名称相同的子例程相同的操作:
     atan2( y, x )返回 y/x 的反正切。
     cos( x )返回 x 的余弦;x 是弧度。
     sin( x )返回 x 的正弦;x 是弧度。
     exp( x )返回 x 幂函数。
     log( x )返回 x 的自然对数。
     sqrt( x )返回 x 平方根。
     int( x )返回 x 的截断至整数的值。
     rand( )返回任意数字 n,其中 0 <= n < 1。
     srand( [Expr] )将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。

字符串函数
字符串函数是:
     gsub( Ere, Repl, [ In ] )除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行,。
     sub( Ere, Repl, [ In ] )用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere
     参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与
     Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。
     index( String1, String2 )在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从
     1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。
     length [(String)]返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0
     记录变量)。
     blength [(String)]返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String
     参数,则返回整个记录的长度($0 记录变量)。
     substr( String, M, [ N ] )返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M
     参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N,则子串的长度将是 M 参数指定的位置到
     String 参数的末尾 的长度。
     match( String, Ere )在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从
     1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH
     特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。
     split( String, A, [Ere] )将 String 参数指定的参数分割为数组元素 A[1], A[2], . . .,
     A[n],并返回 n 变量的值。此分割可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符 FS 特殊变量)来进行(如果没有给出
     Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。
     tolower( String )返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的
     LC_CTYPE 范畴定义。
     toupper( String )返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的
     LC_CTYPE 范畴定义。
     sprintf(Format, Expr, Expr, . . . )根据 Format 参数指定的 printf 子例程格式字符串来格式化
     Expr 参数指定的表达式并返回最后生成的字符串。

一般函数
一般函数是:
     close( Expression )用同一个带字符串值的 Expression 参数来关闭由 print 或 printf 语句打开的或调用
     getline 参数打开的文件或管道。如果文件或管道成功关闭,则返回 0;其它情况下返回非零值。如果打算写一个文件,并稍后在同一个程序中读取文件,则
     close 语句是必需的。
     system(Command )执行 Command 参数指定的命令,并返回出口状态。等同于 system 子例程。
     Expression | getline [ Variable ]从来自 Expression
     参数指定的命令的输出中通过管道传送的流中读取一个输入记录,并将该记录的值指定给 Variable 参数指定的变量。如果当前未打开江
     Expression 参数的值作为其命令名称的流,则创建流。创建的流等同于调用 popen 子例程,此时 Command 参数取
     Expression 参数的值且 Mode 参数设置为一个是 r 的值。只要流保留打开且 Expression 参数求得同一个字符串,则对
     getline 函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。
     getline [ Variable ] < Expression从 Expression 参数指定的文件读取输入的下一个记录,并将
     Variable 参数指定的变量设置为该记录的值。只要流保留打开且 Expression 参数对同一个字符串求值,则对 getline
     函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。
     getline [ Variable ]将 Variable 参数指定的变量设置为从当前输入文件读取的下一个输入记录。如果未指定 Variable
     参数,则 $0 记录变量设置为该记录的值,还将设置 NF、NR 和 FNR 特殊变量。

注:所有 getline 函数的格式对于成功输入返回 1,对于文件结束返回零,对于错误返回 -1。
用户定义的函数
用户定义的函数以下列格式说明:
function Name (Parameter, Parameter,…)  { Statements }
函数可以指向 awk 命令程序中的任何位置,且它的使用可以优先于它的定义。此函数的作用域是全局的。
函数参数可以是标量或数组。参数名称对函数而言是本地的;所有其它变量名称都是全局的。同一个名称不应用作不同的实体;例如,一个参数不能即用作函数名称又用作特殊变量。具有全局作用域的变量不应共享一个函数的名称。同个作用域中的标量和数组不应具有同一个名称。
函数定义中的参数数量不必和调用函数时使用的参数数量匹配。多余的形式参数可用作本地变量。额外的标量初始化后具有等同于空字符串和数字值为
0(零)的字符串值;额外的数组参数初始化为空数组。
当调用函数时,函数名称和左括号之间没有空格。函数调用可以是嵌套的或循环的。从任何嵌套的或循环函数函数调用返回时,所有调用函数的参数的值应保持不变,除了引用传送的数组参数。return
语句可用于返回一个值。
在函数定义内,在左 { (花括号) 之前和右 } (花括号) 之后的换行字符是可选的。
函数定义的一个示例是:
function average ( g,n)
{
       for (i in g)
          sum=sum+g
       avg=sum/n
       return avg
}
数组 g 和变量 n 以及数组中的元素个数传递给函数 average。然后函数获得一个平均值并返回它。
条件语句
awk 命令编程语言中的大部分条件语句和 C 编程语言中的条件语句具有相同的语法和功能。所有条件语句允许使用{ } (花括号)
将语句组合在一起。可以在条件语句的表达式部分和语句部分之间使用可选的换行字符,且换行字符或 ;(分号)用于隔离 { } (花括号) 中的多个语句。C
语言中的六种条件语句是:
     if需要以下语法:
     if ( Expression ) { Statement } [ else Action ]
     while需要以下语法:
     while ( Expression ) { Statement }
     for需要以下语法:
     for ( Expression ; Expression ; Expression ) { Statement }
     break当 break 语句用于 while 或 for 语句时,导致退出程序循环。
     continue当 continue 语句用于 while 或 for 语句时,使程序循环移动到下一个迭代。

awk 命令编程语言中的五种不遵循 C 语言规则的条件语句是:
     for…in需要以下语法:
     for ( Variable in Array ) { Statement }
     for…in 语句将 Variable 参数设置为 Array 变量的每个索引值,一次一个索引且没有特定的顺序,并用每个迭代来执行
     Statement 参数指定的操作。请参阅 delete 语句以获得 for…in 语句的示例。
     if…in需要以下语法:
     if ( Variable in Array ) { Statement }
     if…in 语句搜索是否存在的 Array 元素。如果找到 Array 元素,就执行该语句。
     delete需要以下语法:
     delete Array [ Expression ]
     delete 语句删除 Array 参数指定的数组元素和 Expression 参数指定的索引。例如,语句:
for (i in g)
  delete g;
     将删除 g[] 数组的每个元素。
     exit需要以下语法:
     exit [Expression]
     exit 语句首先调用所有 END 操作(以它们发生的顺序),然后以 Expression 参数指定的出口状态终止 awk 命令。如果 exit
     语句在 END 操作中出现,则不调用后续 END 操作。
     #需要以下语法:
     # Comment
     # 语句放置注释。注释应始终以换行字符结束,但可以在一行上的任何地方开始。
     next停止对当前输入记录的处理,从下一个输入记录继续。

输出语句
awk 命令编程语言的两种输出语句是:
     print需要以下语法:
     print [ ExpressionList ] [ Redirection ] [ Expression ]
     print 语句将 ExpressionList 参数指定的每个表达式的值写至标准输出。每个表达式由 OFS 特殊变量的当前值隔开,且每个记录由
     ORS 特殊变量的当前值终止。
     可以使用 Redirection 参数重定向输出,此参数可指定用 >(大于号)、>>(双大于号)和
     |(管道)进行的三种输出重定向。Redirection 参数如果重定向输出,而 Expression 参数是文件的路径名称(当
     Redirection 参数是 > 或 >> 时)或命令的名称(当 Redirection 参数是 | 时)。
     printf需要以下语法:
     printf Format [ , ExpressionList ] [ Redirection ] [ Expression ]
     printf 语句将 ExpressionList 参数指定的表达式以 Format 参数指定的格式写至标准输出。除了 c
     转换规范(%c)不同外,printf 语句和 printf 命令起完全相同的作用。Redirection 和 Expression 参数与在
     print 语句中起相同的作用。
     对于 c
     转换规范:如果自变量具有一个数字值,则编码是该值的字符将输出。如果值是零或不是字符集中的任何字符的编码,则行为未定义。如果自变量不具有数字值,则输出字符串值的第一个字符;如果字符串不包含任何字符,则行为未定义。

注:如果 Expression 参数为 Redirection 参数指定一个路径名称,则 Expression 参数将括在双引号中以确保将它当作字符串对待。
变量
变量可以是标量、字段变量、数组或特殊变量。变量名称不能以数字开始。
变量可仅用于引用。除了函数参数以外,它们没有明确说明。未初始化的标量变量和数组元素具有一个为 0(零)的数字值和一个为空字符串(” “)的字符串值。
根据上下文,变量呈现出数字或字符串值。每个变量可以具有数字值和/或字符串值。例如:
x = “4” + “8”
将值 12 指定给变量 x。对于字符串常量,表达式应括在 ” “(双引号)中。
数字和字符串间没有显式转换。要促使将表达式当作一个数字,向它添加 0(零)。要促使将表达式当作一个字符串,则添加一个空字符串(” “)。
字段变量
字段变量由 $(美元符号)后跟一个数字或数字表达式来表示。记录中的第一个字段指定为 $1 变量,第二个字段指定为 $2,以次类推。$0
字段变量指定给整个记录。新字段可以通过指定一个值给它们来创建。将一个值指定给不存在的字段(即任何大于 $NF
字段变量的当前值的字段)将促使创建任何干扰字段(指定为空字符串),增加 NF 特殊变量的值,并促使重新计算 $0 记录变量。新字段由当前字段分隔符(FS
特殊变量的值)隔开。空格和跳格是缺省字段分隔符。要更改字段分隔符,请使用 -F 标志或 在 awk 命令程序中为 FS 特殊变量指定另一个值。
数组
数组初始为空且它们大小可动态更改。数组由一个变量和在 [ ](方括号)中的下标来表示。下标或元素标识符可以是几个字符串,它们提供了一种相关数组能力。例如,程序:
/red/  { x[“red”]++ }
/green/ { y[“green”]++ }
增加 red 计数器和 green 计数器的计数。
数组可以用一个以上的下标来建立索引,类似于一些编程语言中的多维数组。因为 awk 命令的编程数组实际上一维的,通过串联各独立表达式的字符串值(每个表达式由
SUBSEP 环境变量的值隔开)来将以逗号隔开的下标转换为单个字符串。所以,以下两个索引操作是等同的:
x[expr1, expr2,…exprn]

x[expr1SUBSEPexpr2SUBSEP…SUBSEPexprn]
当使用 in 运算符时,一个多维 Index 值应包含在圆括号之中。除了 in 运算符,任何对不存在数组元素的引用将自动创建该元素。
特殊变量
以下变量对于 awk 命令具有特殊含义:
     ARGCARGV 数组中的元素个数。此值可以更改。
     ARGV其每个成员包含 File 变量之一或 Assignment 变量之一的数组按序从命令行取出,并从 0(零)编号至 ARGC
     -1。当每个输入文件完成时,ARGV 数组的下一个成员提供下一个输入文件的名称,除非:
       下一个成员是 Assignment 语句,这种情况下对赋值求值。
       下一个成员具有空值,这种情况下跳过该成员。程序可以通过设置 ARGV 数组的包含该输入文件的成员设置为一个空值来跳过所选的输入文件。
       下一个成员是 ARGV [ARGC -1] 的当前值,awk 命令将此成员解释为输入文件的末尾。

     CONVFMT将数字转换为字符串的 printf 格式(除了使用 OFMT 特殊变量的输出语句)。缺省值为“%.6g”。
     ENVIRON表示运行 awk 命令的环境的数组。该数组的每个元素在以下格式中:
     ENVIRON [ “Environment VariableName” ] = EnvironmentVariableValue
     当 awk 命令开始执行时设置这些值,且到执行结束前一直使用该变量,不考虑 ENVIRON 特殊变量的任何修改。
     FILENAME当前输入文件的路径名称。在执行 BEGIN 操作的过程中,FILENAME 的值未定义。在执行 END
     操作的过程中,该值是处理的最后一个输入文件的名称。
     FNR当前文件中的当前输入记录的个数。
     FS输入字段分隔符。缺省值是空格。如果输入字段分隔符是空格,则任何数目的语言环境定义的空格可以分隔字段。FS 特殊变量可以有两种附加的值:
       如果 FS 设置为单个字符,则字段由该字符的每个单个具体值隔开。
       如果 FS 位置为一个扩展正则表达式,则字段由与扩展正则表达式匹配的每个序列的具体值隔开。

     NF当前记录中的字段个数,最大数 99 个。在 BEGIN 操作中,除非先前发出不带 Variable 参数的 getline 函数,否则 NF
     特殊变量未定义。在 END 操作中,除非在输入 END 操作之前发出不带 Variable 参数的后续的、重定向的 getline 函数,否则 NF
     特殊变量保留它为读取的最后一个记录而具有的值。
     NR当前输入记录的个数。在 BEGIN 操作中,NR 特殊变量的值是 0(零)。在 END 操作中,值是最后处理的记录的编号。
     OFMT在输出语句中将数字转换为字符串的 printf 格式。缺省值为“%.6g”。
     OFS输出字段分隔符(缺省值是空格)。
     ORS输出记录分隔符(缺省值是换行字符)。
     RLENGTH由 match 函数来匹配的字符串的长度。
     RS输入记录分隔符(缺省值是换行字符)。如果 RS
     特殊变量为空,则记录以一个或多个空行的序列隔开;第一个空行或最后一个空行在输入的开始和结束都不会产生空记录;换行字符始终是一个字段分隔符,不考虑
     FS 特殊变量的值。
     RSTART由 match 函数来匹配的字符串的起始位置,从 1 开始编号。等同于 match 函数的返回值。
     SUBSEP隔开多个下标。缺省值是 \031。

标志
     -f ProgramFile从 ProgramFile 变量指定的文件获取 awk 命令的指令。如果多次指定 -f
     标志,则文件的串联(按指定的顺序)将用作指令集。
     -F Ere请使用 Ere 变量指定的扩展正则表达式作为字段分隔符。缺省字段分隔符是空格。
     -v Assignment将值指定给 awk 命令编程语言的变量。Assignment 参数的格式是 Name = Value。Name
     部分指定变量的名称并可以是任何下划线、数字或字母字符的组合,但它必须以字母字符或下划线开头。Value
     部分也由下划线、数字和字母数字组成,且前面和后面都有一个 “(双引号字符,类似于字符串值)。如果 Value 部分是数字,则也将为变量指定数字值。
     -v 标志指定的赋值在执行 awk 命令程序的任何部分之前发生,包含 BEGIN 节。
     Assignment将值指定给 awk 命令编程语言的变量。该值和带有 -v 标志的 Assignment
     变量具有相同的格式和功能(除了两者处理的时间不同以外)。Assignment 参数在处于命令行时跟在其后的输入文件(由 File
     变量指定)之前处理。如果指定 Assignment 参数仅优先于多个输入文件的第一个,则赋值在 BEGIN 节后(如果有)就处理。如果
     Assignment 参数出现在最后一个文件后,则在 END 节(如果有)之前处理赋值。如果不指定输入文件,则当读取了标准输入时处理赋值。
     File指定包含要处理的输入的文件的名称。如果不指定 File 变量,或指定了 -(减号),则处理标准输入。
     ‘Program’包含 awk 命令的指令。如果不指定 -f 标志,Program 变量应该是命令行上的第一个项。它应括在 ‘ ‘(单引号)中。

出口状态
该命令返回以下出口值:
     0成功完成。
     >0发生错误。

可以通过使用 exit [ Expression ] 条件语句来更改程序中的出口状态。
示例
要显示长于 72 个字符的文件的行,请输入:
awk  ‘length  >72’  chapter1
这选择 chapter1 文件中长于 72 个字符的每一行,并将这些行写至标准输出,因为未指定 Action。制表符以 1 个字符计数。
要显示字 start 和 stop 之间的所有行,包含“start”和“stop”,请输入:
awk  ‘/start/,/stop/’  chapter1
要运行一个处理文件 chapter1 的 awk 命令程序 sum2.awk,请输入:
awk  -f  sum2.awk  chapter1
以下程序,sum2.awk,计算了输入文件 chapter1 中的第二列的数字的总和与平均值:
   {
      sum += $2
   }
END {
      print “Sum: “, sum;
      print “Average:”, sum/NR;
   }
第一个操作将每行的第二个字段的值添加至变量 sum。当第一次被引用时,所有的变量都初始化为数字值 0(零)。第二个操作前的模式 END
使那些操作在读取了所有输入文件之后才执行。用于计算平均值的 NR 特殊变量是一个指定已经读取的记录的个数的特殊变量。
要以相反顺序打印前两个字段,请输入:
awk ‘{ print $2, $1 }’ chapter1
以下 awk 的程序 sum3.awk 打印文件 chapter2
的前两个字段(输入字段由逗号和/或空格和跳格隔开),然后合计第一列的数字,并打印出总和与平均值:
BEGIN  {FS = “,|[ \t]+”}
      {print $1, $2}
      {s += $1}
END    {print “sum is”,s,”average is”, s/NR }      

其它相关文章:
[color=#FF0000]http://linuxfire.com.cn/~lily/awk.html

[color=#FF0000]http://linuxfire.com.cn/~lily/awk.html

linux下解决大量的TIME_WAIT

vi /etc/sysctl.conf
编辑/etc/sysctl.conf文件,增加三行:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

说明:
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
再执行以下命令,让修改结果立即生效:

/sbin/sysctl -p

用以下语句看了一下服务器的TCP状态:

netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

返回结果如下:
ESTABLISHED 1423
FIN_WAIT1 1
FIN_WAIT2 262
SYN_SENT 1
TIME_WAIT 962
效果:处于TIME_WAIT状态的sockets从原来的10000多减少到1000左右。处于SYN_RECV等待处理状态的sockets为0,原来的为50~300。

通过上面的设置以后,你可能会发现一个新的问题,就是netstat时可能会出现这样的警告:

warning, got duplicate tcp line

这正是上面允许tcp复用产生的警告,不过这不算是什么问题,总比不允许复用而给服务器带来很大的负载合算的多

尽管如此,还是有解决办法的:
1、 安装rpm包:
[root@root2 opt]# rpm -Uvh net-tools-1.60-62.1.x86_64.rpm
Preparing…                ########################################### [100%]
   1:net-tools              ########################################### [100%]
[root@root2 opt]#

对于下载的是源码的rpm则需要使用以下方法安装:

2、 安装rpm源码包方法:
a)         安装src.rpm:
# [root@root1 opt]# rpm -i net-tools-1.60-62.1.src.rpm
……
b)        制作rpm安装包:
[root@root1 opt]# cd /usr/src/redhat/SPECS/
[root@root1 SPECS]# rpmbuild -bb net-tools.spec
c)        rpm包的升级安装:
[root@root1 SPECS]# pwd
/usr/src/redhat/SPECS
[root@root1 SPECS]# cd ../RPMS/x86_64/
[root@root1 x86_64]# rpm -Uvh net-tools-1.60-62.1.x86_64.rpm

3、 再使用netstat来检查时系统正常:

netstat 命令详解

NAME
netstat – Print network connections, routing tables, interface statistics, masquerade connections, and
multicast memberships

SYNOPSIS
netstat [address_family_options] [–tcp|-t] [–udp|-u] [–raw|-w] [–listening|-l] [–all|-a]
[–numeric|-n] [–numeric-hosts][–numeric-ports][–numeric-ports] [–symbolic|-N]
[–extend|-e[–extend|-e]] [–timers|-o] [–program|-p] [–verbose|-v] [–continuous|-c] [delay]

netstat {–route|-r} [address_family_options] [–extend|-e[–extend|-e]] [–verbose|-v] [–numeric|-n]
[–numeric-hosts][–numeric-ports][–numeric-ports] [–continuous|-c] [delay]

netstat {–interfaces|-i} [iface] [–all|-a] [–extend|-e[–extend|-e]] [–verbose|-v] [–program|-p]
[–numeric|-n] [–numeric-hosts][–numeric-ports][–numeric-ports] [–continuous|-c] [delay]

netstat {–groups|-g} [–numeric|-n] [–numeric-hosts][–numeric-ports][–numeric-ports] [–continu-
ous|-c] [delay]

netstat {–masquerade|-M} [–extend|-e] [–numeric|-n] [–numeric-hosts][–numeric-ports][–numeric-
ports] [–continuous|-c] [delay]

netstat {–statistics|-s} [–tcp|-t] [–udp|-u] [–raw|-w] [delay]

netstat {–version|-V}

netstat {–help|-h}

address_family_options:

[–protocol={inet,unix,ipx,ax25,netrom,ddp}[,…]] [–unix|-x] [–inet|–ip] [–ax25] [–ipx]
[–netrom] [–ddp]

中文解释:
-t 显示tcp 连接
-u 显示udp连接
-x 显示unix域协议的连接
–ip 显示ip协议的连接,是和unix域协议相对而言的,但和-x选项不冲突,可同时使用,包括了tcp协议的连接和udp协议的连接
-l 显示listen状态的连接
-a 显示所有状态的连接,是从状态上来讲的all,默认只显示established状态的连接
-p 显示端口对应的程序(program)和pid
-n 以数字的形式显示主机和端口,可以只针对主机名或端口号,–numeric-hosts 或 –numeric-ports
-s 统计网络的状态,此时也可以用-t指定只统计tcp的 -u只统计udp的
delay 参数可以指定延迟多长时间重新执行该命令
-V 显示netstat的版本号

 

注:
1. 这里的连接包括listen ,-t -u可同时使用
2. ip协议有tcp udp两种类型,unix域协议也有stream和dgram 两种类型
3. 上述翻译仅供参考,本人E文有限,不要轻信啊

 

下面说几种 netstat的用法:
1. 查看服务器的TCP状态:
netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
ESTABLISHED 1423
FIN_WAIT1 1
FIN_WAIT2 262
SYN_SENT 1
TIME_WAIT 962

2.netstat中tcp连接状态描述:
状态 描述
CLOSED: 无连接是活动的或正在进行
LISTEN: 服务器在等待进入呼叫
SYN_RECV: 一个连接请求已经到达,等待确认
SYN_SENT: 应用已经开始,打开一个连接
ESTABLISHED: 正常数据传输状态
FIN_WAIT1: 应用说它已经完成
FIN_WAIT2: 另一边已同意释放
ITMED_WAIT: 等待所有分组死掉
CLOSING: 两边同时尝试关闭
TIME_WAIT: 另一边已初始化一个释放
LAST_ACK: 等待所有分组死掉

3. netstat 输出的字段的解释:
 OUTPUT
   Active Internet connections (TCP, UDP, raw)
   Proto
       The protocol (tcp, udp, raw) used by the socket.

   Recv-Q
       The count of bytes not copied by the user program connected to this socket.
       // 是接受队列里的数据,就是还没传给上层的应用程序的

   Send-Q
       The count of bytes not acknowledged by the remote host.
      // 是发送出去,但是还没有被确认的数据

   Local Address
       Address and port number of the local end of the socket.  Unless the –numeric (-n) option is specified, the  socket
       address  is  resolved  to  its canonical host name (FQDN), and the port number is translated into the corresponding
       service name.

   Foreign Address
       Address and port number of the remote end of the socket.  Analogous to "Local Address."

   State
       The state of the socket. Since there are no states in raw mode and usually no states used in UDP, this  column  may
       be left blank. Normally this can be one of several values:

       ESTABLISHED
              The socket has an established connection.

       SYN_SENT
              The socket is actively attempting to establish a connection.

       SYN_RECV
              A connection request has been received from the network.

       FIN_WAIT1
              The socket is closed, and the connection is shutting down.

       FIN_WAIT2
              Connection is closed, and the socket is waiting for a shutdown from the remote end.

       TIME_WAIT
              The socket is waiting after close to handle packets still in the network.

       CLOSED The socket is not being used.

       CLOSE_WAIT
              The remote end has shut down, waiting for the socket to close.

       LAST_ACK
              The remote end has shut down, and the socket is closed. Waiting for acknowledgement.

       LISTEN The  socket  is  listening for incoming connections.  Such sockets are not included in the output unless you
              specify the –listening (-l) or –all (-a) option.

       CLOSING
              Both sockets are shut down but we still don’t have all our data sent.

       UNKNOWN
              The state of the socket is unknown.

   User
       The username or the user id (UID) of the owner of the socket.

   PID/Program name
       Slash-separated pair of the process id (PID) and process name of the  process  that  owns  the  socket.   –program
       causes  this column to be included.  You will also need superuser privileges to see this information on sockets you
       don’t own.  This identification information is not yet available for IPX sockets.

   Timer
       (this needs to be written)

   Active UNIX domain Sockets
   Proto
       The protocol (usually unix) used by the socket.

   RefCnt
       The reference count (i.e. attached processes via this socket).

   Flags
       The flags displayed is SO_ACCEPTON (displayed as ACC), SO_WAITDATA (W) or SO_NOSPACE (N).  SO_ACCECPTON is used  on
       unconnected  sockets if their corresponding processes are waiting for a connect request. The other flags are not of
       normal interest.

   Type
       There are several types of socket access:

       SOCK_DGRAM
              The socket is used in Datagram (connectionless) mode.

       SOCK_STREAM
              This is a stream (connection) socket.

       SOCK_RAW
              The socket is used as a raw socket.

       SOCK_RDM
              This one serves reliably-delivered messages.

       SOCK_SEQPACKET
              This is a sequential packet socket.

       SOCK_PACKET
              Raw interface access socket.

       UNKNOWN
              Who ever knows what the future will bring us – just fill in here 🙂

   State
       This field will contain one of the following Keywords:

       FREE   The socket is not allocated

       LISTENING
              The socket is listening for a connection request.  Such sockets are only included in the output if you spec-
              ify the –listening (-l) or –all (-a) option.

       CONNECTING
              The socket is about to establish a connection.

       CONNECTED
              The socket is connected.

       DISCONNECTING
              The socket is disconnecting.

       (empty)
              The socket is not connected to another one.

       UNKNOWN
              This state should never happen.

   PID/Program name
       Process  ID (PID) and process name of the process that has the socket open.  More info available in Active Internet
       connections section written above.

   Path
       This is the path name as which the corresponding processes attached to the socket.

Lighttpd+Squid+Apache搭建高效率Web服务器

架构原理
Apache通常是开源界的首选Web服务器,因为它的强大和可靠,已经具有了品牌效应,可以适用于绝大部分的应用场合。但是它的强大有时候却显得笨重,配置文件得让人望而生畏,高并发情况下效率不太高。而轻量级的Web服务器Lighttpd却是后起之秀,其静态文件的响应能力远高于Apache,据说是Apache的2-3倍。Lighttpd的高性能和易用性,足以打动我们,在它能够胜任的领域,尽量用它。Lighttpd对PHP的支持也很好,还可以通过Fastcgi方式支持其他的语言,比如Python。

毕竟Lighttpd是轻量级的服务器,功能上不能跟Apache比,某些应用无法胜任。比如Lighttpd还不支持缓存,而现在的绝大部分站点都是用程序生成动态内容,没有缓存的话即使程序的效率再高也很难满足大访问量的需求,而且让程序不停的去做同一件事情也实在没有意义。首先,Web程序是需要做缓存处理的,即把反复使用的数据做缓存。即使这样也还不够,单单是启动Web处理程序的代价就不少,缓存最后生成的静态页面是必不可少的。而做这个是 Squid的强项,它本是做代理的,支持高效的缓存,可以用来给站点做反向代理加速。把Squid放在Apache或者Lighttpd的前端来缓存 Web服务器生成的动态内容,而Web应用程序只需要适当地设置页面实效时间即可。

即使是大部分内容动态生成的网站,仍免不了会有一些静态元素,比如图片、JS脚本、CSS等等,将Squid放在Apache或者Lighttp前端后,反而会使性能下降,毕竟处理HTTP请求是Web服务器的强项。而且已经存在于文件系统中的静态内容再在Squid中缓存一下,浪费内存和硬盘空间。因此可以考虑将Lighttpd再放在Squid的前面,构成 Lighttpd+Squid+Apache的一条处理链,Lighttpd在最前面,专门用来处理静态内容的请求,把动态内容请求通过proxy模块转发给Squid,如果Squid中有该请求的内容且没有过期,则直接返回给Lighttpd。新请求或者过期的页面请求交由Apache中Web程序来处理。经过Lighttpd和Squid的两级过滤,Apache需要处理的请求将大大减少,减少了Web应用程序的压力。同时这样的构架,便于把不同的处理分散到多台计算机上进行,由Lighttpd在前面统一把关。

在这种架构下,每一级都是可以进行单独优化的,比如Lighttpd可以采用异步IO方式,Squid可以启用内存来缓存,Apache可以启用MPM 等,并且每一级都可以使用多台机器来均衡负载,伸缩性很好。

实例讲解
下面以daviesliu.net和rainbud.net域下面的几个站点为例来介绍一下此方案的具体做法。daviesliu.net域下有几个用 mod_python实现的blog站点,几个php的站点,一个mod_python的小程序,以后可能还会架设几个PHP和Django的站点。而服务器非常弱,CPU为Celeron 500,内存为PC 100 384M,因此比较关注Web服务器的效率。这几个站点都是采用虚拟主机方式,开在同一台机器的同一个端口上。

Lighttpd服务于80端口,Squid运行在3128端口,Apache运行在81端口。

Lighttpd的配置
多个域名采用/var/www/domain/subdomain 的目录结构,用evhost模块配置document-root如下:

evhost.path-pattern        =  var.basedir + “/%0/%3/”

FtpSearch中有Perl脚本,需要启用CGI支持,它是用来做ftp站内搜索的,缓存的意义不大,直接由lighttpd的mod_cgi处理:

$HTTP[“url”] =~ “^/cgi-bin/” { # only allow cgi’s in this directory
    dir-listing.activate = “disable”    # disable directory listings
    cgi.assign = ( “.pl”   =>  “/usr/bin/perl”, “.cgi”  =>  “/usr/bin/perl” )
}

bbs使用的是phpBB,访问量不大,可以放在lighttpd(fastcgi)或者apache(mod_php)下,暂时使用 lighttpd,设置所有.php的页面请求有fastcgi处理:

fastcgi.server = ( “.php” =>  ( (  “host”  => “127.0.0.1”, “port”=> 1026,  “bin-path”  =>  “/usr/bin/php-cgi”  )  ) )

blog.daviesliu.net 和 blog.rainbud.net 是用mod_python编写的blogxp程序,所有静态内容都有扩展名,而动态内容没有扩展名。blogxp是用python程序生成XML格式的数据再交由mod_xslt转换成HTML页面,只能放在Apache下运行。该站点采用典型Lighttpd+Squid+Apache方式处理:

$HTTP[“host”] =~ “^blog” {
    $HTTP[“url”] !~ “\.” {      
        proxy.server = ( “” => ( “localhost” => ( “host”=> “127.0.0.1”, “port”=> 3128 ) ) )  #3128端口为
    }
}

share中有静态页面,也有用mod_python处理的请求,在/cgi/下:

$HTTP[“host”] =~ “^share” {
    proxy.server = (
        “/cgi” => ( “localhost” => ( “host”=> “127.0.0.1”, “port”=> 3128 )  )  
    )
}

Squid的配置
只允许本地访问:

http_port   3128
http_access allow localhost
http_access deny all

启用反向代理:

httpd_accel_host 127.0.0.1
httpd_accel_port 81                   #apache的端口
httpd_accel_single_host on
httpd_accel_with_proxy on          #启用缓存
httpd_accel_uses_host_header on #启用虚拟主机支持

此方向代理支持该主机上的所有域名。

Apache的配置
配置/etc/conf.d/apache2,让其加载mod_python、mod_xslt、mod_php模块:

APACHE2_OPTS=”-D PYTHON -D XSLT -D PHP5″

所有网站的根目录:


   AllowOverride All     #允许.htaccess覆盖
    Order allow,deny
    Allow from all

基于域名的虚拟主机:


ServerName blog.daviesliu.net
DocumentRoot /var/www/daviesliu.net/blog

这里明显没有lighttpd的evhost配置方便。

blog.daviesliu.net下的.htaccess设置(便于开发,不用重启Apache):

SetHandler mod_python
PythonHandler blogxp.publisher
PythonDebug On
PythonAutoReload On


    SetHandler None        #静态文件直接由Apache处理


    AddType text/xsl .xsl  #防止对xsl文件进行转化
    AddOutputFilterByType mod_xslt text/xml
    XSLTCache off
    XSLTProcess on

Header set Pragma “cache”
Header set Cache-Control “cache”

在blogxp.publisher里面,还需要设置返回的文档类型和过期时间:

    req.content_type = “text/xml”
    req.headers_out[‘Expires’] = formatdate( time.time() + 60 * 5 )

经过这样的配置,所有站点都可以通过80、3128、81三个端口进行正常访问,80端口用作对外的访问,以减少负荷。81端口可以用作开发时的调试,没有缓存的困扰。

性能测试
由于时间和精力有限,下面只用ab2做一个并不规范的性能对比测试(每项都测多次取平均),评价指标为每秒钟的请求数。
测试命令,以测试lighttpd上并发10个请求 scripts/prototype.js 为例:

ab2 -n 1000 -c 10 http://blog.daviesliu.net:80/scripts/prototype.js

静态内容:prototype.js (27kB)

Con
Lighttpd(:80)
Squid(:3128)
Apache(:81)

1
380
210
240

10
410
215
240

100
380
160
230

可见在静态内容上,Lighttpd表现强劲,而Squid在没有配内存缓存的情况下比另两个Web服务器的性能要差些。

动态页面:/rss (31kB)

Con
Lighttpd(:80)
Squid(:3128)
Apache(:81)

1
103
210
6.17

10
110
200
6.04

100
100
100
6.24

在动态内容上,Squid的作用非常明显,而Lighttpd受限于Squid的效率,并且还要低一大截。如果是有多台Squid来做均衡的话,Lighttpd的功效才能发挥出来。
在单机且静态内容很少的情况下,可以不用Lighttpd而将Squid置于最前面。

VIM快捷键

VIM快捷键:

光标移动:
四个方向
   k
h 0 l
   j

  ctrl+f, ctrl+b                 向下翻页,向上翻页
  ctrl+d, ctrl+u                 向下半翻页,向上半翻页
  $    移动行尾
  0    移动行首
  w    移动下一个词
  b    移动到上一个词
  gg   跳到文档的开始处
  G    跳到文档的末尾
  %    跳到匹配的括号处("{ }""[]""()")
  ctrl+i,tab                  跳到下一个jump point
  ctrl+o   跳到上一个jump point

  23gg, 23G, :23 跳到第23行
  ctrl+i, tab  跳到下一个跳点(Jump Point)
  ctrl+o  跳到上一个跳点

查找替换:
#  从光标向后查找整个关键词
* 从光标向前查找整个关键词
g# 从光标向后查找关键词
g* 从光标向前查找关键词
fx,tx,Fx,Tx    在当前行查找字符

查找替换例子:
: s/SEARCH/REPLACE
: s/If/Since          将下一个"If"换成"Since"
: %s/If/Since       将全部"If"换成"Since"
: 1,3 s/If/Since/g  只对1,3行有效,如无前缀,只对当前行有效

表达式:
. 代替一个字符
* 表示一个或多个字符的重复

/d.*an 可以匹配 dan, divan, debian

单词边界:
指定单词边界: \< 和 \>
如: /\<d[a-z]*an\>    匹配以d开始,中间包含任意个小写字母,以an结束的单词

/\$[0-9]*\.[0-9][0-9] 匹配查找 $XX…X.XX这要的数字,有且只有两位小数的

常用的编辑命令:
a, i   在光标后插入, 在光标前插入
dd  删除一行
cc,S  删除一行后进入insert模式
dw  删除一个单词
cw  删除一个单词后进入insert模式
x,dl  删除一个字符
s,cl  删除一个字符后进入insert模式

p  粘贴
xp  交换两个字符
ddp  交换两行

y  复制
yy  复制一行
u  撤消
ctrl+r                 重做
.  重复上一次修改

ctrl+r                重做
.  重复上一次修改

划分窗格:
:split/vsplit                分隔一个窗口
:new/vnew 创建一个新的窗口
:sf {filename}            在新窗口中打开filename
:close  关闭当前窗口
:only  关闭除当前窗口外所有窗口
:ctrl-w h      到左面的窗口
:ctrl-w j      到下面的窗口
:ctrl-w k      到上面的窗口
:ctrl-w l      到右面的窗口
:ctrl-w t      到顶部的窗口
:ctrl-w b      到底部的窗口

重复操作(宏操作):
q[a-z]  开始记录操作,记录到寄存器[a-z]中
q  停止记录操作
@[a-z]  执行寄存器中的操作
@@  执行最近寄存器中记录的操作
例子: 一个缓冲区有两行:
  sys/types.h
  stdio.h
–>要改为:
  #include <sys/types.h>
  #include <stdio.h>
操作如下:
  qa #开始记录
  ^ #移动行首
  i #进入insert模式
  #include < #输入内容
  $ #移动行尾
  i #进入insert模式
  > #输入内容
  q #停止记录

  移动另一行:
  @a即可执行相同的操作

Visual Mode操作:
ctrl+v                 进入基于块的可视模式
v  进入基于字符的可视模式
V  进入基于行的可视模式

c  删除选定的块
I{string}<ESC> 选定块后按大写的I,输入字符串,再按ESC,可以在块内每一行插入相同的内容

跳到声明处:
[[  向前跳到顶格的第一个"{"
[]  向前跳到顶格的第一个"}"
][  向后跳到顶格的第一个"{"
]]  向后跳到顶格的第一个"}"
[{  跳到本代码块(由{}界定)的开头
[}  跳到本代码块的结尾

Shell:
:ctrl+z/suspend 在shell下是挂起vim; gui下是最小化窗口
:!{command} 执行shell命令
:shell  开一个新的shell

保存vim状态(挂起?):
:mksession session.vim      保存当前vim状态
:source session.vim         回复vim状态
vim -S session.vim         启动vim时恢复session

高效率移动

在插入模式之外

基本上来说,你应该尽可能少的呆在插入模式里面,因为在插入模式里面VIM就像一个“哑巴”编辑器一样。很多新手都会一直呆在插入模式里面,因为这样易于
使用。但VIM的强大之处在于他的命令行模式!你会发现,在你越来越了解VIM之后,你就会花越来越少的时间使用插入模式了。

使用 h,j,k,l

使用VIM高效率编辑的第一步,就是放弃使用箭头键。使用VIM,你就不用频繁的在箭头键和字母键之间移来移去了,这会节省你很多时间。当你在命令模式
时,你可以用h,j,k,l来分别实现左,下,上,右箭头的功能。一开始可能需要适应一下,但一旦习惯这种方式,你就会发现这样操作的高效之处了。

在你编辑你的电子邮件或者其他有段落的文本时,你可能会发现使用方向键和你预期的效果不一样,有时候可能会一次跳过了很多行。这是因为你的段落在VIM看
来是一个大的长长的行。这时你可以在按h,j,k或者l 之前键入一个g,这样VIM就会按屏幕上面的行如你所愿的移动了。

在当前行里面有效的移动光标

很多编辑器只提供了简单的命令来控制光标的移动(比如左,上,右,下,到行首/尾等)。VIM则提供了很多强大的命令来满足你控制光标的欲望。当光标从一
点移动到另外一点,在这两点之间的文本(包括这两个点)称作被“跨过”,这里的命令也被称作是motion。(简单说明一下,后面会用到这个重要的概念)

这里是常用到的一些命令(motion):

fx:移动光标到当前行的下一个x处。很明显,x可以是任意一个字母,而且你可以使用;来重复你的上一个f命令。

tx:和上面的命令类似,但是是移动到x的左边一个位置。(这真的很有用)

Fx:和fx类似,不过是往回找。

w:光标往前移动一个词。

b: 光标往后移动一个词。

0: 移动光标到当前行首。

^:移动光标到当前行的第一个字母位置。

$: 移动光标到行尾。

):移动光标到下一个句子。

( : 移动光标到上一个句子。

在整个文件里面有效移动光标

VIM有很多命令,可以用来到达文件里面你想到达的地方。下面是一些在文件里面移动的命令:

<C-F>:向下移动一屏。

<C-B>:向上移动一屏。

G:到文件尾

numG:移动光标到指定的行(num)。(比如10G就是到第10行)

gg:到文件首

H:移动光标到屏幕上面

M:移动光标到屏幕中间

L:移动光标到屏幕下面

*:读取光标处的字符串,并且移动光标到它再次出现的地方。

#:和上面的类似,但是是往反方向寻找。

/text:从当前光标处开始搜索字符串text,并且到达text出现的地方。必须使用回车来开始这个搜索命令。如果想重复上次的搜索的话,按n。

?text:和上面类似,但是是反方向。

ma:在当前光标的位置标记一个书签,名字为a。书签名只能是小写字母。你看不见书签的存在,但它确实已经在那里了。

a:到书签a处。注意这个不是单引号,它一般位于大部分键盘的1的左边。

.:到你上次编辑文件的地方。这个命令很有用,而且你不用自己去标记它。

高效的输入

使用关键词自动完成

VIM
有一个非常漂亮的关键词自动完成系统。这表示,你可以输入一个长词的一部分,然后按一下某个键,然后VIM就替你完成了这个长词的输入了。举个例子:你有
一个变量名为 iAmALongAndAwkwardVarName 在你写的代码的某个地方。也许你不想每回都自己一个一个字母的去输入它。

使用关键词自动完成功能,你只需要输入开始几个字母(比如iAmAL),然后按<C-N>(按住Ctrl,再按N)或者<C-P>。如果VIM没有给出你想要的词,基本按,直到你满意为止,VIM会一直循环它找到的匹配的字符串。

聪明的进入插入模式

很多新手进入插入模式都只是用i。这样当然可以进入插入模式,但通常不是那么合适,因为VIM提供了很多进入插入模式的命令。下面是最常用的一些:

i:在当前字符的左边插入

I:在当前行首插入

a:在当前字符的右边插入

A:在当前行尾插入

o:在当前行下面插入一个新行

O:在当前行上面插入一个新行

c{motion}:删除motion命令跨过的字符,并且进入插入模式。比如:c$,这将会删除从光标位置到行尾的字符并且进入插入模式。ct!,这会删除从光标位置到下一个叹号(但不包括),然后进入插入模式。被删除的字符被存在了剪贴板里面,并且可以再粘贴出来。

d{motion}:和上面差不多,但是不进入插入模式。

有效的移动大段的文本

使用可视选择(visual selections)和合适的选择模式

不想最初的VI,VIM允许你高亮(选择)一些文本,并且进行操作。这里有三种可视选择模式:

v:按字符选择。经常使用的模式,所以亲自尝试一下它。

V:按行选择。这在你想拷贝或者移动很多行的文本的时候特别有用。

<C-V>:按块选择。非常强大,只在很少的编辑器中才有这样的功能。你可以选择一个矩形块,并且在这个矩形里面的文本会被高亮。

在选择模式的时候使用上面所述的方向键和命令(motion)。比如,vwww,会高亮光标前面的三个词。Vjj将会高亮当前行以及下面两行。

在可视选择模式下剪切和拷贝

一旦你高亮了选区,你或许想进行一些操作:

d:剪贴选择的内容到剪贴板。

y:拷贝选择的内容到剪贴板。

c:剪贴选择的内容到剪贴板并且进入插入模式。

在非可视选择模式下剪切和拷贝

如果你很清楚的知道你想拷贝或者剪切什么,那你根本就不需要进入可视选择模式。这样也会节省时间:

d{motion}:剪切motion命令跨过的字符到剪贴板。比如,dw会剪切一个词而dfS会将从当前光标到下一个S之间的字符剪切至剪贴板。

y{motion}:和上面类似,不过是拷贝。

c{motion}:和d{motion}类似,不过最后进入插入模式。

dd:剪切当前行。

yy:拷贝当前行。

cc:剪切当前行并且进入插入模式。

D:剪切从光标位置到行尾到剪贴板。

Y:拷贝当前行。

C:和D类似,最后进入插入模式。

x:剪切当前字符到剪贴板。

s:和x类似,不过最后进入插入模式。

粘贴

粘贴很简单,按p。

使用多重剪贴板

很多编辑器都只提供了一个剪贴板。VIM有很多。剪贴板在VIM里面被称为寄存器(Registers)。你可以列出当前定义的所有寄存器名和它们的内容,命令为":reg"。最好使用小写字母来作为寄存器的名称,因为大写的有些被VIM占用了。

使用寄存器的命令为双引号“。

比如:我们要拷贝当前行到寄存器k。你应该按 "kyy。(你也可以使用 V"ky。为什么这样也可以呢?)现在当前行应该已经存在了寄存器k里面直到你又拷贝了一些东西进入寄存器k。现在你可以使用命令 "kp 来粘贴寄存器k里面的内容到你想要的位置。

避免重复

令人惊奇的 . 命令

在VI里面,输入 . (小数点符号),将会重复你给入的上一个命令。比如,你上个命令为 'dw'(删除一个词),VI将会接着再删除一个词。

使用数字

使用数字也是VIM强大的而且很节省时间的重要特性之一。在很多VIM的命令之前都可以使用一个数字,这个数字将会告诉VIM这个命令需要执行几次。比如:

3j 将会把光标向下移动三行。

10dd 将会删除十行。

y3" 将会拷贝从当前光标到第三个出现的引号之间的内容到剪贴板。

数字是扩展motion命令作用域非常有效的方法。

记录宏

有时候,你会发现你自己在文章的每段或者每行都重复相同的一系列动作。VIM允许你记录一个宏来完成你的特殊需要。

qregister:记录宏到寄存器register,这里register是任意的你的寄存器的名字。比如qa,将会记录并且把宏存在寄存器a里面。

q:结束宏的记录。

@register:使用存在寄存器register的宏。比如@a,将会使用存在寄存器a里面的宏。

必须要记住的是,宏只记录了你的系列按键并且重复执行它们。它们不是魔法。因为在VIM里面完成目的的方法有很多,所以有时候你要小心选择命令来记录你的宏。因为它们会在所有你要执行它的地方执行。

用VIM写代码

VIM是一个绝好的编辑器来写代码,因为它有一些特性是专门为程序员而设。这里是一些常用的:

)p:和p的功能差不多,但是它会自动调整被粘贴的文本的缩进去适应当前代码的位置。试一下!

%:匹配花括号,方括号,括号等。在一个括号的上面,然后按%,鼠标就会出现在匹配的另外一半括号处。

>>:缩进所有选择的代码

<<:和上面类似,但是反缩进

gd:到达光标所在处函数或者变量的定义处。

K:在Man里面查找光标当前所在处的词