Archive for the ‘Shell’ Category

如何保护自己编写的shell程序

星期一, 04月 28th, 2008

要保护自己编写的shell脚本程序,方法有很多,最简单的方法有两种:1、加密 2、设定过期时间,下面以shc工具为例说明:
一、安装shc工具
shc是一个加密shell脚本的工具.它的作用是把shell脚本转换为一个可执行的二进制文件.
 
shc的下载地址:             
http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.6.tgz

安装:
tar zxvf shc-3.8.tgz
cd shc-3.8
make test
make
make test
make strings
make install  这一步需要root权限
 
二、加密方法:
shc -r -f scrīpt-name  注意:要有-r选项, -f 后跟要加密的脚本名.
运行后会生成两个文件,scrīpt-name.x 和 scrīpt-name.x.c
scrīpt-name.x是加密后的可执行的二进制文件.
./scrīpt-name    即可运行.
scrīpt-name.x.c是生成scrīpt-name.x的原文件(c语言)

三、设定期限:
首先使用shc转化为二进制,并加上过期时间,如
./shc -e 12/06/2006 -m “please contact yazjiyao@yahoo.com.cn” -r -f flushvpn.sh
 
 我一般在程序中加入自动更新系统时间 的命令,防止用户更改系统时间。

$(( )) 與 $( ) 還有${ } 差在哪?

星期六, 04月 26th, 2008

我們上一章介紹了 ( ) 與 { } 的不同,這次讓我們擴展一下,看看更多的變化:$( ) 與 ${ } 又是啥玩意兒呢?

在 bash shell 中,$( ) 與 ` ` (反引號) 都是用來做命令替換用(command substitution)的。
所謂的命令替換與我們第五章學過的變量替換差不多,都是用來重組命令行:
* 完成引號裡的命令行,然後將其結果替換出來,再重組命令行。
例如:
[code]$ echo the last sunday is $(date -d “last sunday” +%Y-%m-%d)[/code]
如此便可方便得到上一星期天的日期了… ^_^

在操作上,用 $( ) 或 ` ` 都無所謂,只是我”個人”比較喜歡用 $( ) ,理由是:

1,  ` ` 很容易與 ‘ ‘ ( 單引號)搞混亂,尤其對初學者來說。
有時在一些奇怪的字形顯示中,兩種符號是一模一樣的(直豎兩點)。
當然了,有經驗的朋友還是一眼就能分辯兩者。只是,若能更好的避免混亂,又何樂不為呢? ^_^

2, 在多層次的復合替換中,` ` 須要額外的跳脫( \` )處理,而 $( ) 則比較直觀。例如:
這是錯的:
[code]command1 `command2 `command3` `[/code]
原本的意圖是要在 command2 `command3` 先將 command3 提換出來給 command 2 處理,
然後再將結果傳給 command1 `command2 …` 來處理。
然而,真正的結果在命令行中卻是分成了 `command2 ` 與 “ 兩段。
正確的輸入應該如下:
[code]command1 `command2 \`command3\` `[/code]

要不然,換成 $( ) 就沒問題了:
[code]command1 $(command2 $(command3))[/code]
只要你喜歡,做多少層的替換都沒問題啦~~~  ^_^

不過,$( ) 並不是沒有斃端的…
首先,` ` 基本上可用在全部的 unix shell 中使用,若寫成 shell script ,其移植性比較高。
而 $( ) 並不見的每一種 shell 都能使用,我只能跟你說,若你用 bash2 的話,肯定沒問題…  ^_^

接下來,再讓我們看 ${ } 吧… 它其實就是用來作變量替換用的啦。
一般情況下,$var 與 ${var} 並沒有啥不一樣。
但是用 ${ } 會比較精確的界定變量名稱的範圍,比方說:
[code]$ A=B
$ echo $AB

[/code]
原本是打算先將 $A 的結果替換出來,然後再補一個 B 字母於其後,
但在命令行上,真正的結果卻是只會提換變量名稱為 AB 的值出來…
若使用 ${ } 就沒問題了:
[code]$ echo ${A}B
BB[/code]

不過,假如你只看到 ${ } 只能用來界定變量名稱的話,那你就實在太小看 bash 了﹗
有興趣的話,你可先參考一下 cu 本版的精華文章:
http://www.chinaunix.net/forum/viewtopic.php?t=201843

為了完整起見,我這裡再用一些例子加以說明 ${ } 的一些特異功能:
假設我們定義了一個變量為:
file=/dir1/dir2/dir3/my.file.txt
我們可以用 ${ } 分別替換獲得不同的值:
${file#*/}:拿掉第一條 / 及其左邊的字串:dir1/dir2/dir3/my.file.txt
${file##*/}:拿掉最後一條 / 及其左邊的字串:my.file.txt
${file#*.}:拿掉第一個 .  及其左邊的字串:file.txt
${file##*.}:拿掉最後一個 .  及其左邊的字串:txt
${file%/*}:拿掉最後條 / 及其右邊的字串:/dir1/dir2/dir3
${file%%/*}:拿掉第一條 / 及其右邊的字串:(空值)
${file%.*}:拿掉最後一個 .  及其右邊的字串:/dir1/dir2/dir3/my.file
${file%%.*}:拿掉第一個 .  及其右邊的字串:/dir1/dir2/dir3/my
記憶的方法為:
[list]# 是去掉左邊(在鑑盤上 # 在 $ 之左邊)
% 是去掉右邊(在鑑盤上 % 在 $ 之右邊)
單一符號是最小匹配﹔兩個符號是最大匹配。[/list]
${file:0:5}:提取最左邊的 5 個字節:/dir1
${file:5:5}:提取第 5 個字節右邊的連續 5 個字節:/dir2

我們也可以對變量值裡的字串作替換:
${file/dir/path}:將第一個 dir 提換為 path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:將全部 dir 提換為 path:/path1/path2/path3/my.file.txt

利用 ${ } 還可針對不同的變數狀態賦值(沒設定、空值、非空值):
${file-my.file.txt} :假如 $file 沒有設定,則使用 my.file.txt 作傳回值。(空值及非空值時不作處理)
${file:-my.file.txt} :假如 $file 沒有設定或為空值,則使用 my.file.txt 作傳回值。 (非空值時不作處理)
${file+my.file.txt} :假如 $file 設為空值或非空值,均使用 my.file.txt 作傳回值。(沒設定時不作處理)
${file:+my.file.txt} :若 $file 為非空值,則使用 my.file.txt 作傳回值。 (沒設定及空值時不作處理)
${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt 。 (空值及非空值時不作處理)
${file:=my.file.txt} :若 $file 沒設定或為空值,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt 。 (非空值時不作處理)
${file?my.file.txt} :若 $file 沒設定,則將 my.file.txt 輸出至 STDERR。 (空值及非空值時不作處理)
${file:?my.file.txt} :若 $file 沒設定或為空值,則將 my.file.txt 輸出至 STDERR。 (非空值時不作處理)

tips:
以上的理解在於, 你一定要分清楚 unset 與 null 及 non-null 這三種賦值狀態.
一般而言, : 與 null 有關, 若不帶 : 的話, null 不受影響, 若帶 : 則連 null 也受影響.

還有哦,${#var} 可計算出變量值的長度:
${#file} 可得到 27 ,因為 /dir1/dir2/dir3/my.file.txt 剛好是 27 個字節…

接下來,再為大家介稍一下 bash 的組數(array)處理方法。
一般而言,A=”a b c def” 這樣的變量只是將 $A 替換為一個單一的字串,
但是改為 A=(a b c def) ,則是將 $A 定義為組數…
bash 的組數替換方法可參考如下方法:
${A[@]} 或 ${A[*]} 可得到 a b c def (全部組數)
${A[0]} 可得到 a (第一個組數),${A[1]} 則為第二個組數…
${#A[@]} 或 ${#A[*]} 可得到 4 (全部組數數量)
${#A[0]} 可得到 1 (即第一個組數(a)的長度),${#A[3]} 可得到 3 (第四個組數(def)的長度)
A[3]=xyz 則是將第四個組數重新定義為 xyz …

諸如此類的….
能夠善用 bash 的 $( ) 與 ${ } 可大大提高及簡化 shell 在變量上的處理能力哦~~~  ^_^

好了,最後為大家介紹 $(( )) 的用途吧:它是用來作整數運算的。
在 bash 中,$(( )) 的整數運算符號大致有這些:
+ - * / :分別為 “加、減、乘、除”。
% :餘數運算
& | ^ !:分別為 “AND、OR、XOR、NOT” 運算。

例:
[code]$ a=5; b=7; c=2
$ echo $(( a+b*c ))
19
$ echo $(( (a+b)/c ))
6
$ echo $(( (a*b)%c))
1[/code]

在 $(( )) 中的變量名稱,可於其前面加 $ 符號來替換,也可以不用,如:
$(( $a + $b * $c)) 也可得到 19 的結果

此外,$(( )) 還可作不同進位(如二進位、八進位、十六進位)作運算呢,只是,輸出結果皆為十進位而已:
echo $((16#2a)) 結果為 42 (16進位轉十進位)
以一個實用的例子來看看吧:
假如當前的  umask 是 022 ,那麼新建文件的權限即為:
[code]$ umask 022
$ echo “obase=8;$(( 8#666 & (8#777 ^ 8#$(umask)) ))” | bc
644[/code]

事實上,單純用 (( )) 也可重定義變量值,或作 testing:
a=5; ((a++)) 可將 $a 重定義為 6
a=5; ((a–)) 則為 a=4
a=5; b=7; ((a < b)) 會得到  0 (true) 的返回值。
常見的用於 (( )) 的測試符號有如下這些:
[list]<:小於
>:大於
<=:小於或等於
>=:大於或等於
==:等於
!=:不等於[/list]
不過,使用 (( )) 作整數測試時,請不要跟 [ ] 的整數測試搞混亂了。(更多的測試我將於第十章為大家介紹)

怎樣?好玩吧..  ^_^  okay,這次暫時說這麼多…
上面的介紹,並沒有詳列每一種可用的狀態,更多的,就請讀者參考手冊文件囉…

找到一篇sed强文:sed1line

星期六, 03月 22nd, 2008

HANDY ONE-LINERS FOR SED (Unix stream editor)               Mar. 23, 2001
compiled by Eric Pement <pemente@northpark.edu>               version 5.1
Latest version of this file is usually at:
   http://www.student.northpark.edu/pemente/sed/sed1line.txt
   http://www.cornerstonemag.com/sed/sed1line.txt
This file is also available in Portuguese at:
   http://www.lrv.ufsc.br/wmaker/sed_ptBR.html

FILE SPACING:

 # double space a file
 sed G

 # double space a file which already has blank lines in it. Output file
 # should contain no more than one blank line between lines of text.
 sed ’/^$/d;G’

 # triple space a file
 sed ’G;G’

 # undo double-spacing (assumes even-numbered lines are always blank)
 sed ’n;d’

NUMBERING:

 # number each line of a file (simple left alignment). Using a tab (see
 # note on ’\t’ at end of file) instead of space will preserve margins.
 sed = filename | sed ’N;s/\n/\t/’

 # number each line of a file (number on left, right-aligned)
 sed = filename | sed ’N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /’

 # number each line of file, but only print numbers if line is not blank
 sed ’/./=’ filename | sed ’/./N; s/\n/ /’

 # count lines (emulates ”wc -l”)
 sed -n ’$=’

TEXT CONVERSION AND SUBSTITUTION:

 # IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format
 sed ’s/.$//’               # assumes that all lines end with CR/LF
 sed ’s/^M$//’              # in bash/tcsh, press Ctrl-V then Ctrl-M
 sed ’s/\x0D$//’            # gsed 3.02.80, but top script is easier

 # IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format
 sed ”s/$/`echo -e \\\r`/”            # command line under ksh
 sed ’s/$’”/`echo \\\r`/”             # command line under bash
 sed ”s/$/`echo \\\r`/”               # command line under zsh
 sed ’s/$/\r/’                        # gsed 3.02.80

 # IN DOS ENVIRONMENT: convert Unix newlines (LF) to DOS format
 sed ”s/$//”                          # method 1
 sed -n p                             # method 2

 # IN DOS ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format
 # Cannot be done with DOS versions of sed. Use ”tr” instead.
 tr -d \r <infile >outfile            # GNU tr version 1.22 or higher

 # delete leading whitespace (spaces, tabs) from front of each line
 # aligns all text flush left
 sed ’s/^[ \t]*//’                    # see note on ’\t’ at end of file

 # delete trailing whitespace (spaces, tabs) from end of each line
 sed ’s/[ \t]*$//’                    # see note on ’\t’ at end of file

 # delete BOTH leading and trailing whitespace from each line
 sed ’s/^[ \t]*//;s/[ \t]*$//’

 # insert 5 blank spaces at beginning of each line (make page offset)
 sed ’s/^/     /’

 # align all text flush right on a 79-column width
 sed -e :a -e ’s/^.\{1,78\}$/ &/;ta’  # set at 78 plus 1 space

 # center all text in the middle of 79-column width. In method 1,
 # spaces at the beginning of the line are significant, and trailing
 # spaces are appended at the end of the line. In method 2, spaces at
 # the beginning of the line are discarded in centering the line, and
 # no trailing spaces appear at the end of lines.
 sed  -e :a -e ’s/^.\{1,77\}$/ & /;ta’                     # method 1
 sed  -e :a -e ’s/^.\{1,77\}$/ &/;ta’ -e ’s/\( *\)\1/\1/’  # method 2

 # substitute (find and replace) ”foo” with ”bar” on each line
 sed ’s/foo/bar/’             # replaces only 1st instance in a line
 sed ’s/foo/bar/4′            # replaces only 4th instance in a line
 sed ’s/foo/bar/g’            # replaces ALL instances in a line
 sed ’s/\(.*\)foo\(.*foo\)/\1bar\2/’ # replace the next-to-last case
 sed ’s/\(.*\)foo/\1bar/’            # replace only the last case

 # substitute ”foo” with ”bar” ONLY for lines which contain ”baz”
 sed ’/baz/s/foo/bar/g’

 # substitute ”foo” with ”bar” EXCEPT for lines which contain ”baz”
 sed ’/baz/!s/foo/bar/g’

 # change ”scarlet” or ”ruby” or ”puce” to ”red”
 sed ’s/scarlet/red/g;s/ruby/red/g;s/puce/red/g’   # most seds
 gsed ’s/scarlet\|ruby\|puce/red/g’                # GNU sed only

 # reverse order of lines (emulates ”tac”)
 # bug/feature in HHsed v1.5 causes blank lines to be deleted
 sed ’1!G;h;$!d’               # method 1
 sed -n ’1!G;h;$p’             # method 2

 # reverse each character on the line (emulates ”rev”)
 sed ’/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//’

 # join pairs of lines side-by-side (like ”paste”)
 sed ’$!N;s/\n/ /’

 # if a line ends with a backslash, append the next line to it
 sed -e :a -e ’/\\$/N; s/\\\n//; ta’

 # if a line begins with an equal sign, append it to the previous line
 # and replace the ”=” with a single space
 sed -e :a -e ’$!N;s/\n=/ /;ta’ -e ’P;D’

 # add commas to numeric strings, changing ”1234567″ to ”1,234,567″
 gsed ’:a;s/\B[0-9]\{3\}\>/,&/;ta’                     # GNU sed
 sed -e :a -e ’s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta’  # other seds

 # add commas to numbers with decimal points and minus signs (GNU sed)
 gsed ’:a;s/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g;ta’

 # add a blank line every 5 lines (after lines 5, 10, 15, 20, etc.)
 gsed ’0~5G’                  # GNU sed only
 sed ’n;n;n;n;G;’             # other seds

SELECTIVE PRINTING OF CERTAIN LINES:

 # print first 10 lines of file (emulates behavior of ”head”)
 sed 10q

 # print first line of file (emulates ”head -1″)
 sed q

 # print the last 10 lines of a file (emulates ”tail”)
 sed -e :a -e ’$q;N;11,$D;ba’

 # print the last 2 lines of a file (emulates ”tail -2″)
 sed ’$!N;$!D’

 # print the last line of a file (emulates ”tail -1″)
 sed ’$!d’                    # method 1
 sed -n ’$p’                  # method 2

 # print only lines which match regular expression (emulates ”grep”)
 sed -n ’/regexp/p’           # method 1
 sed ’/regexp/!d’             # method 2

 # print only lines which do NOT match regexp (emulates ”grep -v”)
 sed -n ’/regexp/!p’          # method 1, corresponds to above
 sed ’/regexp/d’              # method 2, simpler syntax

 # print the line immediately before a regexp, but not the line
 # containing the regexp
 sed -n ’/regexp/{g;1!p;};h’

 # print the line immediately after a regexp, but not the line
 # containing the regexp
 sed -n ’/regexp/{n;p;}’

 # print 1 line of context before and after regexp, with line number
 # indicating where the regexp occurred (similar to ”grep -A1 -B1″)
 sed -n -e ’/regexp/{=;x;1!p;g;$!N;p;D;}’ -e h

 # grep for AAA and BBB and CCC (in any order)
 sed ’/AAA/!d; /BBB/!d; /CCC/!d’

 # grep for AAA and BBB and CCC (in that order)
 sed ’/AAA.*BBB.*CCC/!d’

 # grep for AAA or BBB or CCC (emulates ”egrep”)
 sed -e ’/AAA/b’ -e ’/BBB/b’ -e ’/CCC/b’ -e d    # most seds
 gsed ’/AAA\|BBB\|CCC/!d’                        # GNU sed only

 # print paragraph if it contains AAA (blank lines separate paragraphs)
 # HHsed v1.5 must insert a ’G;’ after ’x;’ in the next 3 scripts below
 sed -e ’/./{H;$!d;}’ -e ’x;/AAA/!d;’

 # print paragraph if it contains AAA and BBB and CCC (in any order)
 sed -e ’/./{H;$!d;}’ -e ’x;/AAA/!d;/BBB/!d;/CCC/!d’

 # print paragraph if it contains AAA or BBB or CCC
 sed -e ’/./{H;$!d;}’ -e ’x;/AAA/b’ -e ’/BBB/b’ -e ’/CCC/b’ -e d
 gsed ’/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d’         # GNU sed only

 # print only lines of 65 characters or longer
 sed -n ’/^.\{65\}/p’

 # print only lines of less than 65 characters
 sed -n ’/^.\{65\}/!p’        # method 1, corresponds to above
 sed ’/^.\{65\}/d’            # method 2, simpler syntax

 # print section of file from regular expression to end of file
 sed -n ’/regexp/,$p’

 # print section of file based on line numbers (lines 8-12, inclusive)
 sed -n ’8,12p’               # method 1
 sed ’8,12!d’                 # method 2

 # print line number 52
 sed -n ’52p’                 # method 1
 sed ’52!d’                   # method 2
 sed ’52q;d’                  # method 3, efficient on large files

 # beginning at line 3, print every 7th line
 gsed -n ’3~7p’               # GNU sed only
 sed -n ’3,${p;n;n;n;n;n;n;}’ # other seds

 # print section of file between two regular expressions (inclusive)
 sed -n ’/Iowa/,/Montana/p’             # case sensitive

SELECTIVE DELETION OF CERTAIN LINES:

 # print all of file EXCEPT section between 2 regular expressions
 sed ’/Iowa/,/Montana/d’

 # delete duplicate, consecutive lines from a file (emulates ”uniq”).
 # First line in a set of duplicate lines is kept, rest are deleted.
 sed ’$!N; /^\(.*\)\n\1$/!P; D’

 # delete duplicate, nonconsecutive lines from a file. Beware not to
 # overflow the buffer size of the hold space, or else use GNU sed.
 sed -n ’G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P’

 # delete the first 10 lines of a file
 sed ’1,10d’

 # delete the last line of a file
 sed ’$d’

 # delete the last 2 lines of a file
 sed ’N;$!P;$!D;$d’

 # delete the last 10 lines of a file
 sed -e :a -e ’$d;N;2,10ba’ -e ’P;D’   # method 1
 sed -n -e :a -e ’1,10!{P;N;D;};N;ba’  # method 2

 # delete every 8th line
 gsed ’0~8d’                           # GNU sed only
 sed ’n;n;n;n;n;n;n;d;’                # other seds

 # delete ALL blank lines from a file (same as ”grep ’.' ”)
 sed ’/^$/d’                           # method 1
 sed ’/./!d’                           # method 2

 # delete all CONSECUTIVE blank lines from file except the first; also
 # deletes all blank lines from top and end of file (emulates ”cat -s”)
 sed ’/./,/^$/!d’          # method 1, allows 0 blanks at top, 1 at EOF
 sed ’/^$/N;/\n$/D’        # method 2, allows 1 blank at top, 0 at EOF

 # delete all CONSECUTIVE blank lines from file except the first 2:
 sed ’/^$/N;/\n$/N;//D’

 # delete all leading blank lines at top of file
 sed ’/./,$!d’

 # delete all trailing blank lines at end of file
 sed -e :a -e ’/^\n*$/{$d;N;ba’ -e ’}'  # works on all seds
 sed -e :a -e ’/^\n*$/N;/\n$/ba’        # ditto, except for gsed 3.02*

 # delete the last line of each paragraph
 sed -n ’/^$/{p;h;};/./{x;/./p;}’

SPECIAL APPLICATIONS:

 # remove nroff overstrikes (char, backspace) from man pages. The ’echo’
 # command may need an -e switch if you use Unix System V or bash shell.
 sed ”s/.`echo \\\b`//g”    # double quotes required for Unix environment
 sed ’s/.^H//g’             # in bash/tcsh, press Ctrl-V and then Ctrl-H
 sed ’s/.\x08//g’           # hex expression for sed v1.5

 # get Usenet/e-mail message header
 sed ’/^$/q’                # deletes everything after first blank line

 # get Usenet/e-mail message body
 sed ’1,/^$/d’              # deletes everything up to first blank line

 # get Subject header, but remove initial ”Subject: ” portion
 sed ’/^Subject: */!d; s///;q’

 # get return address header
 sed ’/^Reply-To:/q; /^From:/h; /./d;g;q’

 # parse out the address proper. Pulls out the e-mail address by itself
 # from the 1-line return address header (see preceding script)
 sed ’s/ *(.*)//; s/>.*//; s/.*[:<] *//’

 # add a leading angle bracket and space to each line (quote a message)
 sed ’s/^/> /’

 # delete leading angle bracket & space from each line (unquote a message)
 sed ’s/^> //’

 # remove most HTML tags (accommodates multiple-line tags)
 sed -e :a -e ’s/<[^>]*>//g;/</N;//ba’

 # extract multi-part uuencoded binaries, removing extraneous header
 # info, so that only the uuencoded portion remains. Files passed to
 # sed must be passed in the proper order. Version 1 can be entered
 # from the command line; version 2 can be made into an executable
 # Unix shell script. (Modified from a script by Rahul Dhesi.)
 sed ’/^end/,/^begin/d’ file1 file2 … fileX | uudecode   # vers. 1
 sed ’/^end/,/^begin/d’ ”$@” | uudecode                    # vers. 2

 # zip up each .TXT file individually, deleting the source file and
 # setting the name of each .ZIP file to the basename of the .TXT file
 # (under DOS: the ”dir /b” switch returns bare filenames in all caps).
 echo @echo off >zipup.bat
 dir /b *.txt | sed ”s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/” >>zipup.bat

TYPICAL USE: Sed takes one or more editing commands and applies all of
them, in sequence, to each line of input. After all the commands have
been applied to the first input line, that line is output and a second
input line is taken for processing, and the cycle repeats. The
preceding examples assume that input comes from the standard input
device (i.e, the console, normally this will be piped input). One or
more filenames can be appended to the command line if the input does
not come from stdin. Output is sent to stdout (the screen). Thus:

 cat filename | sed ’10q’        # uses piped input
 sed ’10q’ filename              # same effect, avoids a useless ”cat”
 sed ’10q’ filename > newfile    # redirects output to disk

For additional syntax instructions, including the way to apply editing
commands from a disk file instead of the command line, consult ”sed &
awk, 2nd Edition,” by Dale Dougherty and Arnold Robbins (O’Reilly,
1997; http://www.ora.com), ”UNIX Text Processing,” by Dale Dougherty
and Tim O’Reilly (Hayden Books, 1987) or the tutorials by Mike Arst
distributed in U-SEDIT2.ZIP (many sites). To fully exploit the power
of sed, one must understand ”regular expressions.” For this, see
“Mastering Regular Expressions” by Jeffrey Friedl (O’Reilly, 1997).
The manual (”man”) pages on Unix systems may be helpful (try ”man
sed”, ”man regexp”, or the subsection on regular expressions in ”man
ed”), but man pages are notoriously difficult. They are not written to
teach sed use or regexps to first-time users, but as a reference text
for those already acquainted with these tools.

QUOTING SYNTAX: The preceding examples use single quotes (’…’)
instead of double quotes (”…”) to enclose editing commands, since
sed is typically used on a Unix platform. Single quotes prevent the
Unix shell from intrepreting the dollar sign ($) and backquotes
(`…`), which are expanded by the shell if they are enclosed in
double quotes. Users of the ”csh” shell and derivatives will also need
to quote the exclamation mark (!) with the backslash (i.e., \!) to
properly run the examples listed above, even within single quotes.
Versions of sed written for DOS invariably require double quotes
(”…”) instead of single quotes to enclose editing commands.

USE OF ’\t’ IN SED SCRIPTS: For clarity in documentation, we have used
the expression ’\t’ to indicate a tab character (0×09) in the scripts.
However, most versions of sed do not recognize the ’\t’ abbreviation,
so when typing these scripts from the command line, you should press
the TAB key instead. ’\t’ is supported as a regular expression
metacharacter in awk, perl, and HHsed, sedmod, and GNU sed v3.02.80.

VERSIONS OF SED: Versions of sed do differ, and some slight syntax
variation is to be expected. In particular, most do not support the
use of labels (:name) or branch instructions (b,t) within editing
commands, except at the end of those commands. We have used the syntax
which will be portable to most users of sed, even though the popular
GNU versions of sed allow a more succinct syntax. When the reader sees
a fairly long command such as this:

   sed -e ’/AAA/b’ -e ’/BBB/b’ -e ’/CCC/b’ -e d

it is heartening to know that GNU sed will let you reduce it to:

   sed ’/AAA/b;/BBB/b;/CCC/b;d’      # or even
   sed ’/AAA\|BBB\|CCC/b;d’

In addition, remember that while many versions of sed accept a command
like ”/one/ s/RE1/RE2/”, some do NOT allow ”/one/! s/RE1/RE2/”, which
contains space before the ’s’. Omit the space when typing the command.

OPTIMIZING FOR SPEED: If execution speed needs to be increased (due to
large input files or slow processors or hard disks), substitution will
be executed more quickly if the ”find” expression is specified before
giving the ”s/…/…/” instruction. Thus:

   sed ’s/foo/bar/g’ filename         # standard replace command
   sed ’/foo/ s/foo/bar/g’ filename   # executes more quickly
   sed ’/foo/ s//bar/g’ filename      # shorthand sed syntax

On line selection or deletion in which you only need to output lines
from the first part of the file, a ”quit” command (q) in the script
will drastically reduce processing time for large files. Thus:

   sed -n ’45,50p’ filename           # print line nos. 45-50 of a file
   sed -n ’51q;45,50p’ filename       # same, but executes much faster

If you have any additional scripts to contribute or if you find errors
in this document, please send e-mail to the compiler. Indicate the
version of sed you used, the operating system it was compiled for, and
the nature of the problem. Various scripts in this file were written
or contributed by:

 Al Aab <af137@freenet.toronto.on.ca>   # ”seders” list moderator
 Edgar Allen <era@sky.net>              # various
 Yiorgos Adamopoulos <adamo@softlab.ece.ntua.gr>
 Dale Dougherty <dale@songline.com>     # author of ”sed & awk”
 Carlos Duarte <cdua@algos.inesc.pt>    # author of ”do it with sed”
 Eric Pement <pemente@northpark.edu>    # author of this document
 Ken Pizzini <ken@halcyon.com>          # author of GNU sed v3.02
 S.G. Ravenhall <stew.ravenhall@totalise.co.uk> # great de-html script
 Greg Ubben <gsu@romulus.ncsc.mil>      # many contributions & much help

Mysql备份脚本 带压缩 显示压缩率 日志

星期五, 03月 21st, 2008

#!/bin/sh
#
# Copyright (C), 2007 bug All Rights Reserved

# Title       : Database Backup Script
# Author      : BUG
# File        : db_bak.sh
# Version     : 1.1.0
# Date        : 2008-03-21
# Email       : efbbb27115@homtail.com
# License     : General Public License (GPL) v2
# Description : Database Backup Script
#

initial() {

    echo -en “\33[2J"

    echo -en "\33[0;0H"

    echo -en "\33[32m"

    echo "------------------------------------------------------------"

    echo "---                Database Backup Script                ---"

    echo "------------------------------------------------------------"

    echo -en "\33[37m"

    stty -echo

    umask 077

    mysqln=`echo 'show databases;' | /usr/local/mysql/bin/mysql -psjldafhkg | sed -n '3,$p'`

    mysqlu="root"

    mysqlp="********"

    binpath="/usr/local/mysql/bin"

    dstpath="/pri/bak/sql_bak/"

    runuser=`ps aux | grep $$ | sed -n "1p" | awk '{ print $1 }'`

    mkdir -p $dstpath/`date +%y%m%d`

    exec 3>>$dstpath/`date +%y%m%d`/db_bak.log

}initialecho -e "\n[`date +%y/%m/%d\ %H:%M:%S`] Database Backup Script start by $runuser PID:$$” >&3if [ -f "$dstpath/`date +%y%m%d`/lock" ]

then

    echo -e “\33[33mIt's has completed by `cat $dstpath/\`date +%y%m%d\`/lock`!!!\33[37m"

    echo "[`date +%y/%m/%d\ %H:%M:%S`] It’s has completed by `cat $dstpath/\`date +%y%m%d\`/lock`!!!” >&3

else

    echo -e “Database\tExport\tCompress\tSql\tTgz\tRate”

    echo -e “\33[32m------------------------------------------------------------\33[37m"

    cd $dstpath/`date +%y%m%d`

    for db in $mysqln

    do

    echo -n "$db"

    $binpath/mysqldump --opt -u$mysqlu -p$mysqlp $db > $dstpath/`date +%y%m%d`/$db.sql 2> /dev/null

    RETVAL1=$?

    if [ $RETVAL1 -eq 0 ]

    then

    sqlsize=`du -k $db.sql | cut -f1`

    echo -n “[`date +%y/%m/%d\ %H:%M:%S`]“ >&3

    echo -n “$db” | awk ‘{printf ” %-17s”, $1}’ >&3

    echo -n “OK  ” >&3

    echo -en “\r\t\t  \33[32mOK\33[37m\t"

    tar -czvf $db.tgz $db.sql > /dev/null 2>&1

        RETVAL2=$?

        if [ $RETVAL2 -eq 0 ]

        then

        tgzsize=`du -k $db.tgz | cut -f1`

        echo “OK” >&3

        rm -f $dstpath/`date +%y%m%d`/$db.sql

        echo -en “   \33[32mOK\33[37m"

        echo -en "\33[33m"

        echo -en "$sqlsize" | awk '{printf "%12dKB", $1}'

        echo -en "$tgzsize" | awk '{printf "%6sKB", $1}'

        echo "$sqlsize $tgzsize" | awk '{printf "%8.0f%",$2/$1*100}'

        echo -e "\33[37m"

        else

        echo "Compress fail return $RETVAL2" >&3

        echo -e "  \33[31mfail\33[37m"

        fi

    else

    echo -n "[`date +%y/%m/%d\ %H:%M:%S`]“ >&3

    echo -n “$db” | awk ‘{printf ” %-17s “, $1}’ >&3

    echo “Export fail return $RETVAL1″ >&3

    echo -en “\r\t\t   \33[31mfail\33[37m”

    fi

    done

    echo “`date +%H:%M:%S`”>$dstpath/`date +%y%m%d`/lock

fi

find命令详解

星期四, 01月 31st, 2008

功能说明:查找文件或目录。

语  法:find [目录...][-amin <分钟>][-anewer <参考文件或目录>][-atime <24小时数>][-cmin <分钟>][-cnewer <参考文件或目录>][-ctime <24小时数>][-daystart][-depyh][-empty][-exec <执行指令>][-false][-fls <列表文件>][-follow][-fprint <列表文件>][-fprint0 <列表文件>][-fprintf <列表文件><输出格式>][-fstype <文件系统类型>][-gid <群组识别码>][-group <群组名称>][-help][-ilname <范本样式>][-iname <范本样式>][-inum <inode编号>][-ipath <范本样式>][-iregex <范本样式>][-links <连接数目>][-lname <范本样式>][-ls][-maxdepth <目录层级>][-mindepth <目录层级>][-mmin <分钟>][-mount]
[-mtime <24小时数>][-name <范本样式>][-newer <参考文件或目录>][-nogroup][noleaf] [-nouser][-ok <执行指令>][-path <范本样式>][-perm <权限数值>][-print][-print0][-printf <输出格式>][-prune][-regex <范本样式>][-size <文件大小>][-true][-type <文件类型>][-uid <用户识别码>][-used <日数>][-user <拥有者名称>][-version][-xdev][-xtype <文件类型>]

补充说明:find指令用于查找符合条件的文件。任何位于参数之前的字符串都将被视为欲查找的目录。

参  数:
 -amin<分钟>  查找在指定时间曾被存取过的文件或目录,单位以分钟计算。
 -anewer<参考文件或目录>  查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录。
 -atime<24小时数>  查找在指定时间曾被存取过的文件或目录,单位以24小时计算。
 -cmin<分钟>  查找在指定时间之时被更改的文件或目录。
 -cnewer<参考文件或目录>  查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录。
 -ctime<24小时数>  查找在指定时间之时被更改的文件或目录,单位以24小时计算。
 -daystart  从本日开始计算时间。
 -depth  从指定目录下最深层的子目录开始查找。
 -expty  寻找文件大小为0 Byte的文件,或目录下没有任何子目录或文件的空目录。
 -exec<执行指令>  假设find指令的回传值为True,就执行该指令。
 -false  将find指令的回传值皆设为False。
 -fls<列表文件>  此参数的效果和指定”-ls”参数类似,但会把结果保存为指定的列表文件。
 -follow  排除符号连接。
 -fprint<列表文件>  此参数的效果和指定”-print”参数类似,但会把结果保存成指定的列表文件。
 -fprint0<列表文件>  此参数的效果和指定”-print0″参数类似,但会把结果保存成指定的列表文件。
 -fprintf<列表文件><输出格式>  此参数的效果和指定”-printf”参数类似,但会把结果保存成指定的列表文件。
 -fstype<文件系统类型>  只寻找该文件系统类型下的文件或目录。
 -gid<群组识别码>  查找符合指定之群组识别码的文件或目录。
 -group<群组名称>  查找符合指定之群组名称的文件或目录。
 -help或–help  在线帮助。
 -ilname<范本样式>  此参数的效果和指定”-lname”参数类似,但忽略字符大小写的差别。
 -iname<范本样式>  此参数的效果和指定”-name”参数类似,但忽略字符大小写的差别。
 -inum<inode编号>  查找符合指定的inode编号的文件或目录。
 -ipath<范本样式>  此参数的效果和指定”-ipath”参数类似,但忽略字符大小写的差别。
 -iregex<范本样式>  此参数的效果和指定”-regexe”参数类似,但忽略字符大小写的差别。
 -links<连接数目>  查找符合指定的硬连接数目的文件或目录。
 -iname<范本样式>  指定字符串作为寻找符号连接的范本样式。
 -ls  假设find指令的回传值为True,就将文件或目录名称列出到标准输出。
 -maxdepth<目录层级>  设置最大目录层级。
 -mindepth<目录层级>  设置最小目录层级。
 -mmin<分钟>  查找在指定时间曾被更改过的文件或目录,单位以分钟计算。
 -mount  此参数的效果和指定”-xdev”相同。
 -mtime<24小时数>  查找在指定时间曾被更改过的文件或目录,单位以24小时计算。
 -name<范本样式>  指定字符串作为寻找文件或目录的范本样式。
 -newer<参考文件或目录>  查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录。
 -nogroup  找出不属于本地主机群组识别码的文件或目录。
 -noleaf  不去考虑目录至少需拥有两个硬连接存在。
 -nouser  找出不属于本地主机用户识别码的文件或目录。
 -ok<执行指令>  此参数的效果和指定”-exec”参数类似,但在执行指令之前会先询问用户,若回答”y”或”Y”,则放弃执行指令。
 -path<范本样式>  指定字符串作为寻找目录的范本样式。
 -perm<权限数值>  查找符合指定的权限数值的文件或目录。
 -print  假设find指令的回传值为True,就将文件或目录名称列出到标准输出。格式为每列一个名称,每个名称之前皆有”./”字符串。
 -print0  假设find指令的回传值为True,就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行。
 -printf<输出格式>  假设find指令的回传值为True,就将文件或目录名称列出到标准输出。格式可以自行指定。
 -prune  不寻找字符串作为寻找文件或目录的范本样式。
 -regex<范本样式>  指定字符串作为寻找文件或目录的范本样式。
 -size<文件大小>  查找符合指定的文件大小的文件。
 -true  将find指令的回传值皆设为True。
 -typ<文件类型>  只寻找符合指定的文件类型的文件。
 -uid<用户识别码>  查找符合指定的用户识别码的文件或目录。
 -used<日数>  查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算。
 -user<拥有者名称>  查找符合指定的拥有者名称的文件或目录。
 -version或–version  显示版本信息。
 -xdev  将范围局限在先行的文件系统中。
 -xtype<文件类型>  此参数的效果和指定”-type”参数类似,差别在于它针对符号连接检查

Bash中对变量的操作

星期六, 01月 26th, 2008

1.条件变量替换:
  Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换,替换
条件放在{}中.
  (1) ${value:-word}
      当变量未定义或者值为空时,返回值为word的内容,否则返回变量的值.
  (2) ${value:=word}
      与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将
      word赋值给value
  (3) ${value:?message}
      若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若
      此替换出现在Shell程序中,那么该程序将终止运行)
  (4) ${value:+word}
      若变量以赋值的话,其值才用word替换,否则不进行任何替换
  (5) ${value:offset}
      ${value:offset:length}
      从变量中提取子串,这里offset和length可以是算术表达式.
  (6) ${#value}
      变量的字符个数
  (7) ${value#pattern}
      ${value##pattern}
      去掉value中与pattern相匹配的部分,条件是value的开头与pattern相匹配
      #与##的区别在于一个是最短匹配模式,一个是最长匹配模式.
  (8) ${value%pattern}
      ${value%%pattern}
      于(7)类似,只是是从value的尾部于pattern相匹配,%与%%的区别与#与##一样
  (9) ${value/pattern/string}
      ${value//pattern/string}
      进行变量内容的替换,把与pattern匹配的部分替换为string的内容,/与//的区
      别与上同

注意:上述条件变量替换中,除(2)外,其余均不影响变量本身的值
2.变量的算术运算
  在Bash Shell中,只能进行两个整数间的运算,其结果仍为整数.要进行算术
运算,需要使用let命令,语法为:
  let expr
  expr是一个包含项和操作符的表达式,项可以是一个变量或是一个整数常数,
当使用整数常数时,其默认为十进制整数,用户可以用radio#number来指定其它
形式的整数,其中radio定义了整数是几进制表示的,number是该整数的值.若
radio>10,那么数字字符可从0-9和A-Z.
  在表达式中支持的操作符及其含义为:
  +,-,*,/,%     加,减,乘,除,取模
  >>,<<,&,^,|   左移,右移,位与,位异或,位或
  ?:            三元运算符.与C语言中的定义一致
  ~             取补码
  !,>=,<=,>,<,==,!=,&&,||
  =,+=,-=,*=,/=,%=,<<=,>>=,&=,^=,|=
  表达式式中也可以使用括号.括号或运算优先级的定义与一般计算机语言中的
相同.
  let命令具有返回值.当计算结果(若有多个表达式时,以最后一个为准)为0时,
返回值为1,否则为0.
  当表达式中含有shell的特殊字符(如|)时,需要用引用符(’或”)将其引用起来.
  使用let时还需要注意的时,对于let x+y这样的式子,shell虽然计算了x+y的值
但却将结果丢弃,若不想这样,可以使用let sum=x+y将x+y的结果保存在变量sum中
  另外还可以使用((和))操作符取代let命令,而且这样的话,还可以省去对算术
表达式的引用,如果想返回表达式的值,则需用$(())的格式.

最佳VIM技巧

星期一, 01月 14th, 2008

—————————————-
# 信息来源
—————————————-
www.vim.org : 官方站点
comp.editors : 新闻组
http://www.newriders.com/books/opl/ebooks/0735710015.html : Vim书籍
http://vimdoc.sourceforge.net/cgi-bin/vim2html2.pl : 关于vim的可查询文档
http://vimdoc.sourceforge.net/vimfaq.html : VIM FAQ
—————————————-
# 基础
—————————————-
* # g* g# : 寻找光标处的狭义单词(<cword>) (前向/后向)
% : 括号配对寻找 {}[]()
matchit.vim : 使得 % 能够配对标记 
<script> <?php 等等
<C-N><C-P> : 插入模式下的单词自动完成
<C-X><C-L> : 行自动完成(超级有用)
/<C-R><C-W> : 把狭义单词 <cword> 写到 搜索命令 行
/<C-R><C-A> : 把广义单词 <cWORD> 写到 搜索命令 行
:set ignorecase : 搜索时忽略大小写
:syntax on : 在 Perl,HTML,PHP 等中进行语法着色
:h regexp<C-D> : 按下 control-D 键即可得到包含有 regexp 的帮助主题的列表
: (使用TAB可以实现帮助的自动补齐)
—————————————-
# 使更新 _vimrc 更容易
:nmap ,s :source $VIM/_vimrc
# 译释:nmap 是绑定一个在normal模式下的快捷键
:nmap ,v :e $VIM/_vimrc
# 译释:在normal模式下,先后按下 ,s 两个键执行_vimrc,而 ,v 则是编辑_vimrc
—————————————-
# visual 模式 (例子是:轻松添加其它的 HTML Tags)
:vmap sb “zdi<C-R>z<ESC> :在visual模式下选中的文字前后分别加上和
# 译释:vmap 是绑定一个在visual模式下的快捷键# 译释:原理:在visual模式下,”zd 把一个选中的区域命名为z 然后删除,
# i 进入插入模式,输入,<C-R>z 撤销刚才的删除,然后再写入,
# 最后<ESC>返回normal模式

# 译释:”z 命令创建一个选中的区域为register,并把它命名为z

# 译释:更令人开心的有:在visual模式下选中几行,然后输入 2> ,
# 则选中的行会全部缩进两个tab
# 555,偶一开始还是用 :xx,xx s/^/tt/,好傻啊!

:vmap st “zdi<?= <C-R>z ?><ESC> :在visual模式下选中的文字前后分别加上<?= 和 ?>
—————————————-
# 文件浏览
:Ex : 开启目录浏览器,注意首字母E是大写的
:Sex : 在一个分割的窗口中开启目录浏览器
:ls : 显示当前buffer的情况
:cd .. : 进入父目录
:args : 显示目前打开的文件
:lcd %:p:h : 更改到当前文件所在的目录
# 译释:lcd是紧紧改变当前窗口的工作路径,% 是代表当前文件的文件名,
# 加上 :p扩展成全名(就是带了路径),加上 :h析取出路径

:autocmd BufEnter * lcd %:p:h : 自动更改到当前文件所在的目录
# 译释:autocmd指定一个自动命令,BufEnter指定一个事件,* 指定事件的对象,
# lcd %:p:h 指定一个动作
# hehe,好象和写记叙文差不多
—————————————-
# 缓冲区(buffer)浏览器 (第三方的一个最流行的脚本)
# 需要下载 bufexplorer.vim ,http://www.vim.org/script.php?script_id=42 上就有
be : 在缓冲区浏览器中打开缓冲区列表
bs : 以分割窗口的形式打开缓冲区浏览器
—————————————-
# 大小写转换
guu : 行小写
gUU : 行大写
g~~ : 行翻转(当然指大小写啦)
# 译释: g 是大小写转换命令(greate),u/U/~是三种转换形式(小写/大写/翻转),
# 最后一个重复则表示该转换是对于一行而言的

guw : 字大写(狭义字) 译注:建议对比iw
gUw : 字小写(狭义字)
g~w : 字翻转(狭义字)
# 译释:最后一个w 表示该转换是对于一个字而言的,由于是在normal模式下,
# 所以这个w 表示一个狭义字<cword>

vEU : 字大写(广义字)
vE~ : 字翻转(广义字)
# 译释:vE 这个指令组合会进入visual模式,然后选择一个广义字<CWORD>

ggguG : 把整个文章全部小写(ft!bt!)
gf : 取当前光标处的广义字作为文件名,然后试图打开它!
# 译释:为什么是广义字呢?因为这样可以方便的取到路径啊,像/var/www/html/index.htm

ga : 显示光标处字符的ascii,hex,oct,…晕菜的一堆转换
ggVGg? : 用rot13编码整个文件(晕!)
# 译释:gg到文件首行首字符,V进入Visual-Line模式,G到文件末行首字符,
# 这样就选中了整篇文章,然后g?就是用rot13编码整个文件啦
#
# 【关于rot13——谁让英文是偶数个字母啊】
# ROT13 是一种简单的编码,它把字母分成前后两组,每组13个,编码和译码
# 的算法相同,仅仅交换字母的这两个部分,即:[a..m] –> [n..z] 和 [n..z]
# –> [a..m] 。 ROT13 用简易的手段使得信件不能直接被识别和阅
# 读,也不会被搜索匹配程序用通常的方法直接找到。经常用于 USENET 中发表一
# 些攻击性或令人不快的言论或有简单保密需要的文章。
# 由于 ROT13 是自逆算法,所以,译码和编码是同一个过程。

<C-A>,<C-X> : 增加,减少 光标处的狭义字所表示的数字
:(,仅仅是分割了这两个命令,不是命令的一部分)
: Win32的用户可能需要重新定义一下Ctrl-A,呵呵
# 译注:good guy, 令人不得不想到perl的数字符串

<C-R>=5*5 : 插入25 (这是一个迷你计算器耶!)
—————————————-
# 好玩的东东
:h 42 : 也可以访问 http://www.google.com/search?q=42
: 第一个结果就是 News. Douglas Adams 1952 - 2001.
: Floor 42 extends its deepest sympathies to
: the family, friends, and fans of Douglas Adams.
:h holy-grail
:h!
—————————————-
# 标记和移动
‘. : 跳到最后修改的那一行 (超级有用)(ft,怎么又是这个评价)
`. : 不仅跳到最后修改的那一行,还要定位到修改点
<C-O> : 依次沿着你的跳转记录向回跳 (从最近的一次开始)
<C-I> : 依次沿着你的跳转记录向前跳
:ju(mps) : 列出你跳转的足迹
:help jump-motions
:history : 列出历史命令记录
:his c : 命令行命令历史
:his s : 搜索命令历史
q/ : 搜索命令历史的窗口
q: : 命令行命令历史的窗口
:<C-F> : 历史命令记录的窗口
—————————————-
# 缩写和键盘映像(原文中文件举例都用了c:/aaa/x,偶全给他改成/path/file了,哼唧)
:map <f7> :’a,’bw! /path/file
# 译释:map是映像一个normal模式下的键
# 这里是把F7键映像成把标记a到标记b中间的内容另存为一个文件/path/file
# 标记(mark)的方法:把光标移动到需要标记的地方,输入m,然后输入标记名,例如a

# 引用标记的方法:’a ,即:单引号加标记名

:map <f8> :r /path/file
# 译释:把F8键映像成在当前位置插入文件/path/file的内容
:map <f11> :.w! /path/file2<CR>
# 译释:.(点号)表示当前行
# 所以F11就是把当前行存为/path/file2
# 最后的<CR>表示一个回车
:map <f12> :r /path/file2<CR>
:ab php : 列出php表示的缩写
# 译释:定义一个缩写使用::iab hm hmisty
# 一个有趣的现象是,它列出的会是php和它的前子串开头的缩写
# 例如,有这么几个缩写:
# h => hmisty1 , hm => hmisty2 , hmi => hmisty3, m => hmisty4
# 那么使用 :ab hm会显示这么几个缩写:hm 和 h
# 而不是你想象中的 hm 和 hmi

:map , : 列出以逗号开始的键盘映像
# 译释:一般而言,我们称这些逗号开始的组合键为「逗号命令」
# 不过hmisty更喜欢用;构成「分号命令」
# 而且不是用map,而是用imap
# 因为偶懒么,懒得按<Esc>,所以直接在insert模式下就执行命令了
# 为什么用分号呢?因为我最常用它写程序啊
# perl/C/C++/object pascal/java,都是用分号结束一个语句
# 我们一般很少在分号后面连续写其它字符
# 所以用「分号+其它键」就很少会在输入的时候造成冲突

# 在键盘映像中常用的表示
<CR> : 回车
<ESC> : Esc
<LEADER> : 转义符号
<BAR> : 管道符号 |
—————————————-
# 列出寄存器(Registers)
:reg : 显示所有当前的registers
“1p : “表示引用register,1表示一个名字叫做1的register,
: p就是粘贴(paste)命令
# 译释:”也用来定义register
# 先输入 “,表示定义register
# 然后输入名字,如0~9,a~z
# 然后执行删除或复制命令,如dd或y,
# 或者是visual模式下的d(删除选中的部分)或y(复制选中的部分)
# 则被删除或复制的部分就被存入了这个命名的register
#
# 观察:一个特殊的register, “” ,里面存储了一个匿名的删除/复制
# 在你执行dd或y的时候,被作用的部分被存到了”"中
# 这些和perl是多么像啊
—————————————-
# Useful trick
ayy@a : 把当前行作为一个Vim命令来执行
# 译释:”ayy 是定义当前行到register a,然后@a是执行register a中存储的指令
# yy: 复制一行
# 10yy: 复制从此向下的10行

yy@” : 用上面所提到的那个匿名register
—————————————-
# 从其它程序获取输出 (需要外部程序)
:r!ls.exe : 读取ls的输出到当前位置
!!date : 读取date的输出 (但是会替换当前行的内容)
# 译释:其实你输入了!!后,vim就自动转换到 :.! 等待你继续输入

# 使用外部程序sort进行排序(sort是Unix标准命令,ls,date也是)
:%!sort -u : 使用sort程序排序整个文件(用结果重写文件)
# 译释:%表示整个文件的所有行
# !sort表示执行外部命令sort
# -u是sort的参数,man sort看看,这个参数的意义是合并相同的行
# u就是unique,如果两行内容相同,则结果中只保留一行的说

:’a,’b!sort -u : 对mark a 到mark b中间的内容进行排序
!1} sort -u : 排序当前段落 (只能在normal模式下使用!!)
# 译释:!表示使用filter,1}表示filter的对象是从当前行开始向后数一段
# 段落指到空行处结束,不包括空行
# 其实你一旦输入 !1},vim就自动计算当前段落应该到那一行(eg.+5),然后生成
# :.,.+5! 等待之后输入sort -u,回车,完成操作
# .表示当前行,.+5当然就是当前行向后数5行
—————————————-
# 多文檔操作 (基础)
# 译注:用 :ls! 可以显示出当前所有的buffer
:bn : 跳转到下一个buffer
:bp : 跳转到上一个buffer
:wn : 存盘当前文件并跳转到下一个(又是「超级……」,ft!)
:wp : 存盘当前文件并跳转到上一个
:bd : 把这个文件从buffer列表中做掉
:bun : 卸掉buffer (关闭这个buffer的窗口但是不把它从列表中做掉)
:badd file.c : 把文件file.c添加到buffer列表
:b 3 : 跳到第3个buffer
:b main : 跳到一个名字中包含main的buffer,例如main.c
: (ultra,这个怎么翻译?:()
:sav php.html : 把当前文件存为php.html并打开php.html
:sav! %<.bak : 换一个后缀保存
:e! : 返回到修改之前的文件(修改之后没有存盘)
:w /path/% : 把文件存到一个地儿
:e # : 编辑标记为#的buffer(这个buffer必须含有一个可编辑的文件)
: 用ls命令就能看到哪一个buffer有#
: %a表示当前正在编辑的buffer
: u 表示不能编辑或者已经被做掉的buffer
:e #3 : 编辑编号为3的buffer(这个buffer必须含有一个可编辑的文件)
:rew : 回到第一个可编辑的文件
:brew : 回到第一个buffer
:sp fred.txt : 在一个水平分割的窗口中打开文件fred.txt
# 译注:vs fred.txt可以实现垂直分割
:sball : 把当前所有含有可编辑文件的buffer显示到一个分割窗口中
: (偶该考虑把super翻译成 高级指令 了,ft)
:map <F5> :ls<CR>:e # : 在normal模式下按F5键,则会显示所有含有一个

: 可编辑文件的buffer,然后提示你输入buffer的序号,
: 输入后回车,则编辑这个buffer
# 译注:这是一个键盘绑定

:set hidden : 允许不保存buffer而切换buffer (w/o=without)
—————————————-
# 在分割窗口中快速切换
:map <C-J> <C-W>j<C-W>_
# 译注:原文此处有误,前面应该加上冒号
# 这是一个键盘绑定,把Ctrl-J定义成切换到下一个窗口并最大化
:map <C-K> <C-W>k<C-W>_
—————————————-
# 命令录制 (最佳技巧,ft)
qq #录制到q
.. #输入一系列复杂的指令
q #再次按q停止录制
@q #执行q中存储的指令
@@ #重复执行
# 编辑register/录制
“ap #把register a中的内容贴到当前位置
.. #现在你可以修改它了
“add#删除之,重新存入register a
@a #执行register a中的指令
—————————————-
# _vimrc基础
:set incsearch : 实时匹配你输入的内容
:set wildignore=*.o,*.obj,*.bak,*.exe : tab键的自动完成现在会忽略这些
:set shiftwidth=4 : 现在自动缩进将是4个字符
# 译注:一个tab位通常是8个字符
# 所以,我们还要设定 :set tabstop=4,这样,所有的缩进都是4字符了
# emacs默认就是4字符缩进吧?
:set vb t_vb=”. : 沉默方式(不要叫beep!)
—————————————-
# 加载windows iexplorer来浏览(我想这只有在windows下用gvim才能用到)
:nmap ,f :update<CR>:silent !start c:progra~1intern~1iexplore.exe file://%:p
# 译释:nmap是做一个normal模式下的键盘绑定
# 这里绑定了一个逗号命令 ,f
# :update是写这个文件,与:w不同,它只有当文件被修改了的时候才写
# :silent别让弹出窗口报告执行结果
# !…后面就是执行windows命令了。呵呵,去问bill gates什么意思吧。
# 不过偶用gvim 6.1试过了,好用!

:nmap ,i :update<CR>: !start c:progra~1intern~1iexplore.exe <cWORD><CR>
—————————————-
# 用VIM编辑ftp文件
:cmap ,r :Nread ftp://209.51.134.122/public_html/index.html
:cmap ,w :Nwrite ftp://209.51.134.122/public_html/index.html
# 译注:原文丢失了开头的冒号
# cmap是命令(command)模式绑定

gvim ftp://209.51.134.122/public_html/index.html
# 这一句就是开始编辑一个ftp远程的文件,ft
—————————————-
# 附加到一个register (就是用大写的register名字啦!)
“a5yy #复制5行到a中
10j #下移10行
“A5yy #再添加5行到a中
—————————————-
[I : 显示光标处的狭义字可以匹配的行(高级指令)
# 译注:# 可以全文查找与光标处的狭义字相匹配的字,
# 这在查找函数原型和实现,或者变量使用的时候很有用
----------------------------------------
# 常规缩进
:'a,'b>>
# 译释:把mark a到mark b之间的内容进行两次缩进

# 在visual模式下缩进 (无限可重复)
:vnoremap < <gv
# 译释::vnoremap 重定义了visual模式下 < 符号的含义
# 把它定义成 <gv
# 即:先<向外缩进,然后gv重新选择上一次选择了的区域
# 这样在visual模式下就可以实现连续按<而连续缩进了
:vnoremap > >gv
# 同里,内缩
----------------------------------------
# 查找(译注:建议先学习正则表达式)
# 译注:查找命令不用进入:命令模式,直接按/就可以了
# 如果没有修饰,可以不要右边的/
# 和smth bbs差不多啦,呵呵
/joe/e : 光标停留在匹配单词最后一个字母处
/joe/e+1 : 光标停留在匹配单词最后一个字母的下一个字母处
/joe/s : 光标停留在匹配单词第一个字母处
/^joe.*fred.*bill/ : ft,标准正则表达式
/^[A-J]+/ : 找一个以A~J中一个字母重复两次或以上开头的行
/forum(_.)*pent : 多行匹配
/fred_s*joe/i : 中间可以有任何空白,包括换行符n
# 译注:这个和perl不太一样的哦
/fred|joe : 匹配FRED或JOE
/<fred>/i : 匹配fred,fred必须是一个独立的单词,而不是子串
# 译注:这和perl也不太一样,perl是用b做单词定界符的
/<dddd> : 匹配4个数字
<d{4}> : 也是匹配4个数字
# 在visual模式下查找
:vmap g/ y/<C-R>”<CR> : 匹配选中的高亮文字
# 译释:vmap是在visual模式下的键盘映像
# 映像了g/这个命令组合
# y 把选中的高亮文字写入匿名register ”
# / 打开搜索模式
# <C-R> 准备粘贴register
# ” 粘贴了”"中的内容
# <CR> 回车,执行

:vmap <silent> g/ y/<C-R>=escape(@”, ‘/.*$^~[]‘)<CR><CR> : with spec chars
# 译释:@#$&^*@#%&*#$@!

# 跨行匹配,_ 表示允许匹配换行符,或者说,允许匹配新行
# 译注:小心,和perl不一样
/<!–_p{-}–> : 匹配多行注释
/fred_s*joe/i : 似乎上面有了,ft
/bugs(_.)*bunny : 中间可以有无数东西
:h _ : 看看关于 _ 的帮助

# 查找当前光标位置所在子例程/函数(subroutine/function)的声明
:nmap gx yiw/^(sub<bar>function)s+<C-R>”<CR>
# 译释:nmap 做一个normal模式下的键盘绑定
# y 进入复制状态,后面需要一个motion
# 接着就用 iw 指出了这个motion,是inner word
# inner word也是狭义字<cword>,但是和 w 不同
# w 是从光标位置开始向后看
# 而inner word总是把光标移到第一个字母,从而总能得到一个完整的狭义字
# 试一试 gUw 和 gUiw 就知道区别了,呵呵。

# 在多个文档中搜索
:bufdo /searchstr

:argdo /searchstr
—————————————-
# 替换
# 译注:替换命令需要先进入:命令模式

:%s/fred/joe/igc : 一个常见的替换命令,修饰符igc和perl中一样意思
:%s/r//g : 删除DOS方式的回车^M
:%s= *$== : 删除行尾空白
:’a,’bg/fred/s/dick/joe/igc : 非常有用!(ft,又来了!)
# 译释:’a,’b指定一个范围:mark a ~ mark b
# g//用一个正则表达式指出了进行操作的行必须可以被fred匹配
# 看后面,g//是一个全局显示命令
# s/dick/joe/igc则对于这些满足条件的行进行替换

# 列复制
# 译注:@#%&^#*^%#$!
:%s= [^ ]+$=&&= : 复制最后一列
:%s= f+$=&&= : 一样的功能
:%s= S+$=&& : ft,还是一样
# 反向引用,或称记忆
:s/(.*):(.*)/2 : 1/ : 颠倒用:分割的两个字段
:%s/^(.*)n1/1$/ : 删除重复行
# 非贪婪匹配,{-}
:%s/^.{-}pdf/new.pdf/ : 只是删除第一个pdf
# 跨越可能的多行
:%s/<!–_.{-}–>// : 又是删除多行注释(咦?为什么要说「又」呢?)
:help /{-} : 看看关于 非贪婪数量符 的帮助
:s/fred/<c-r>a/g : 替换fred成register a中的内容,呵呵
# 写在一行里的复杂命令
:%s/f+.gif>/r&r/g | v/.gif$/d | %s/gif/jpg/
# 译注:就是用 | 管道啦

# 或者
:%s/suck|buck/loopy/gc : 或者(或者需要,ft!,|不是或者)
# ft, 不就是转义了么!这个和perl真是不同了!

# 调用VIM函数
:s/__date__/=strftime(”%c”)/ : 插入时间串

# 处理列,替换所有在第三列中的str1
:%s:((w+s+){2})str1:1str2:

# 交换第一列和最后一列 (共4列)
:%s:(w+)(.*s+)(w+)$:321:

# filter all form elements into paste register
# 把所有的form元素(就是html里面的form啦)放到register里?
# ft, 头疼,不解释了
:redir @*|sil exec ‘g#<(input|select|textarea|/=form)>#p’|redir END
:nmap ,z :redir @*<Bar>sil exec selecttextarea/=fo”>’g@<(input<Bar>select<Bar>textarea<Bar>/=fo
# 上面这一行不能完全显示,最好Copy Article下去看

—————————————-
# 全局(global)显示命令,就是用 :g+正则表达式
# 译释: :g/{pattern}/{cmd} 就是全局找到匹配的行
# 然后对这些行执行命令{cmd}
:g/<fred>/ : 显示所有能够为单词fred所匹配的行
:g/<pattern>/z#.5 : 显示内容,还有行号,呵呵
:g/<pattern>/z#.5|echo “==========” : 漂亮的显示,ft!

# 全局命令 (其它)
:g/^s*$/d : 删除所有空行
:g!/^dd/d : 删除不含字符串’dd’的行
:v/^dd/d : 同上
# 译释:v == g!,就是不匹配!
:g/fred/,/joe/d : not line based (very powerfull)
:v/./.,/./-1join : 压缩空行
:g/^$/,/./-j : 压缩空行
:g/<input|<form/p : 或者 要用|
:g/^/pu _ : 把文中空行扩增一倍 (pu = put)
: 即:原来两行间有一个空行,现在变成2个
:g/^/m0 : 按行翻转文章 (m = move)
:g/fred/t$ : 拷贝行,从fred到文件末尾(EOF)
:%norm jdd : 隔行删除
# 译释:% 指明是对所有行进行操作
# norm指出后面是normal模式的指令
# j是下移一行,dd是删除行

# incrementing numbers
:.,$g/^d/exe “norm! <c-a>” : 增加在BOL(beginning of line)处的数字
# 译注:.,$ 指明命令从当前行执行到最后一行
# 如果没有 .,$ 限定范围,那么g//就会对整个文件进行操作
# exe 是执行后面的命令组合

:.,$g/^d/exe “norm <c-p>” : Win32下必须重定义Ctrl-A

# 保存全局命令的结果 (注意必须使用添加模式)
:g/fred/y A : 添加所有为fred所匹配的行到register a
:’a,’b g/^Error/ . w >> errors.txt

# 复制每一行,然后在复制出来的每一行两侧加上一个 print ‘复制出来的内容’
:g/./yank|put|-1s/’/”/g|s/.*/Print ‘&’/
—————————————-
# 全局命令和替换命令联姻 (强大的编辑能力)
:’a,’bg/fred/s/joe/susan/gic : 可以使用反向引用来匹配
:g/fred/,/joe/s/fred/joe/gic : non-line based (ultra)
—————————————-
# 先找fred,然后找joe,然后#$^$%^#$%^@%^%&%^*!
:/fred/;/joe/-2,/sid/+3s/sally/alley/gIC
—————————————-
# 复位向到register * 和 粘贴register *
:redir @* : 复位向命令的输出结果(最下方命令行上的结果)
: 到register * (ft,* 代表0~1,a~z,..)
:redir END : 结束复位向
# 处理粘贴
“*yy : 上面讲过了,就是复制到register *中
“*p : 然后贴出来
—————————————-
:redir >> out.txt : 复位向到一个文件
—————————————-
# 重新格式化文本
gq<CR>
gqap (a是motion p是段落(visual模式))
ggVGgq 重新格式化整个文章
—————————————-
# 对多个文档实施命令
:argdo %s/foo/bar/ : 对所有:args列表中的文档执行命令
:bufdo %s/foo/bar/
:windo %s/foo/bar/
:argdo exe ‘%!sort’|w! : 使用外部命令
—————————————-
# 命令行的一些好玩的东东
gvim -h : 激活的时候激活帮助(Win32)
vi -h 或 vim -h : 这个是unix下用
ls | gvim - : 编辑一个数据流!
gvim -o file1 file2 : 以分割窗口打开两个文件

# 指出打开之后执行的命令
gvim.exe -c “/main” joe.c : 打开joe.c,然后跳转到’main’

# 对一个文件执行多个命令
vim -c “%s/ABC/DEF/ge | update” file1.c

# 对一组文件执行多个命令
vim -c “argdo %s/ABC/DEF/ge | update” *.c

# 自动编辑文件 (编辑命令序列Ex commands已经包含在convert.vim中了)
vim -s “convert.vim” file.c

# 不要加载.vimrc和任何plugins (激活一个干净的VIM)
gvim -u NONE -U NONE -N
—————————————-
# GVIM 不同的地方
gvim -d file1 file2 : vimdiff (比较不同)
dp : 把光标处的不同放到另一个文件
do : 在光标处从另一个文件取得不同
—————————————-
# Vim陷阱
# 在vim的正则表达式中, + 和 | 都必须加转义符
# 小心,这和perl不一样!
/fred+/ : 匹配fred或freddy但是不匹配free
—————————————-
# v ,或叫做very magic (通常都是这么叫)可以取消转义符
/codes(n|s)*where : 普通的正则表达式
/vcodes(n|s)*where : very magic,| 不用加 了!

—————————————-
# 把东西送到命令行/搜索行 (SUPER:偶不再翻译这种叹词了)
<C-R><C-W> : 送一个狭义词
<C-R><C-A> : 送一个广义词
<C-R>- : 送一个小型删除寄存器register
<C-R>[0-9a-z] : 送一个命名寄存器register
<C-R>% : 送文件名过去 (#也行)
—————————————-
# 操作寄存器
:let @a=@_ : 清除register a
:let @*=@a : 寄存器赋值
:map <f11> “qyy:let @q=@q.”zzz”
# 译注:猜猜这个无聊的绑定是什么意思?
—————————————-
# 关于帮助的帮助
:h quickref : 翻到VIM Quick Reference页(有用!)
:h tips : Vim自己的tips
:h visual<C-D><tab> : 得到一个关于visual关键词的帮助列表
: 然后用tab键去选择
:h ctrl<C-D> : 显示所有关于Ctrl的帮助
:h :r : :ex冒号命令
:h CTRL-R : 普通模式命令
:h r : r在正则表达式中是什么意思呢?
:h i_CTRL-R : insert模式下的Ctrl-R
:h c_CTRL-R : 命令行(command-line)模式下的Ctrl-R
:h v_CTRL-V : visual模式下的Ctrl-V
:h tutor : VIM 指南
gvim -h : 关于 VIM 命令的帮助
vi/vim -h
<C-S>T : Control Shift T go backwards in help
: 偶不清楚有什么用:(
—————————————-
# 选项设置在哪里?
:scriptnames : 列出所有加载的 plugins, _vimrcs
:verbose set history : 显示history的值并指出设置文件的位置
—————————————-
# 制作你自己的VIM帮助
:helptags /vim/vim61/doc : 重建 /doc 中所有的 *.txt 帮助文件
:help add-local-help
—————————————-
# 用外部程序来运行程序 (例如 perl :)
map <f2> :w<CR>:!perl -c %<CR>
# 译释::w<CR>写文件
# :!perl -c %<CR>用perl来运行当前文件
# 当前文件必须有文件名!
—————————————-
# 插入DOS换行符
:%s/nubian/<C-V><C-M>&/g : Ctrl-V是一种转义,它说要解释<C-M>
:%s/nubian/<C-Q><C-M>&/g : 对于Win32应该这样
:%s/nubian/^M&/g : 你看到的^M是一个字符
:%s/nubian/r&/g : 更好的形式
—————————————-
# 把最后一个命令贴到当前位置
i<c-r>:
# 把最后一个搜索指令贴到当前位置
i<c-r>/
# 译释:i是进入insert模式,
# Ctrl-r是开启插入模式下register的引用
# :和/分别引用了两个register的内容
—————————————-
# 更多的完成功能
<C-X><C-F> :插入当前目录下的一个文件名到当前位置
# 在insert模式下使用
# 然后用 Ctrl-P/Ctrl-N 翻页
—————————————-
# 替换一个visual区域
# 选择一个区域,然后输入 :s/Emacs/Vim/ 等等,vim会自动进入:模式
:’<,’>s/Emacs/Vim/g : 前面的’<,’>是vim自动添加的
—————————————-
# 在文件中插入行号(不是显示行号,是插入!)
:g/^/exec “s/^/”.strpart(line(”.”).” “, 0, 4)
—————————————-
# 用VIM的方式来编号行
:set number :显示行号
:set nonu :取消显示
:%s/^/=strpart(line(’.').” “,0,&ts)

#从任意行开始编号(需要perl,嘿嘿)
:’a,’b!perl -pne ‘BEGIN{$a=223} substr($_,2,0)=$a++’
#似乎有点小问题,你试试看:)

qqmnYP`n^Aq : 记录到q 然后用 @q 重复
#似乎不能工作,你试试看:)

# 递增已存在数字到文件末
:.,$g/^d/exe “normal! <c-a>”

# 高级递增,看:
http://vim.sourceforge.net/tip_view.php?tip_id=150
—————————————-
# 高级递增 (”真的很有用”,ft)
” 把下面几句放到 _vimrc #vimrc脚本用 ” 做行注释符
let g:I=0
function! INC(increment)
let g:I =g:I + a:increment
return g:I
endfunction
” 例如从mark a 到mark b 递增,从223开始,步长为5
:let I=223
:’a,’bs/$/=INC(5)/
” (原文:create a map for INC)
” 但是cab是清楚命令行缩写啊?怎么回事?
cab viminc :let I=223 | ‘a,’bs/$/=INC(5)/
—————————————-
# 加密(小心使用,不要忘了密码)

:X : 然后vim会提示你输入密码
:h :X
—————————————-
# modeline (make a file readonly etc) must be in first/last 5 lines
# 不会用,不翻了
// vim:noai:ts=2:sw=4:readonly:
:h modeline
—————————————-
# Creating your own GUI Toolbar entry
# 对于text模式下的vim没用,不翻了
amenu Modeline.Insert a VIM modeline <Esc><Esc>ggOvim:ff=unix ts=4 ss=4<CR>v
—————————————-
# 一个保存当前光标下的狭义字到一个文件的函数
function! SaveWord() “这里用!是强制覆盖以前的定义
normal yiw
exe ‘:!echo ‘.@0.’ >> word.txt’
endfunction
map ,p :call SaveWord() #使用该函数的一个例子
—————————————-
# 删除重复行的函数
function! Del()
if getline(”.”) == getline(line(”.”) - 1)
norm dd
endif
endfunction

:g/^/ call Del() #使用该函数的一个例子
—————————————-
# 双字节编码 (non alpha-numerics)
:digraphs : 显示编码表
:h dig : 帮助
i<C-K>e’ : 输入 é
i<C-V>233 : 输入 é (Unix)
i<C-Q>233 : 输入 é (Win32)
ga : 查看字符的hex值
—————————————-
# 文件名自动完成 (例如 main_c.c)
:e main_<tab> : tab 键完成
gf : 打开光标处广义字命名的文件 (normal模式)
main_<C-X><C-F> : 文件名自动完成(insert模式)
—————————————-
# Vim复杂使用
# 交换两个单词
:%s/<(on|off)>/=strpart(”offon”, 3 * (”off” == submatch(0)), 3)/g
—————————————-
# 把text文件转换成html文件(oh,ft)
:runtime! syntax/2html.vim : 转换 txt 成 html
:h 2html : 看看帮助
—————————————-
# VIM 有一个内部自带的 grep 命令
:grep some_keyword *.c : 得到一个包含some_keyword的c文件名列表
:cn : 去下一个出现的位置
—————————————-
# 强制无后缀文件的语法着色方式 .pl
:set syntax=perl
# 取消语法着色
:set syntax off
# 改变色彩主题 (在~vim/vim??/colors中的任何文件)
:colorscheme blue
—————————————-
:set noma (non modifiable) : 防止修改
:set ro (Read Only) : 只读保护
—————————————-
# Sessions (打开一系列文件)
gvim file1.c file2.c lib/lib.h lib/lib2.h :在”session”中加载一系列文件
:mksession : 生成一个Session文件 (默认是Session.vim)
:q
gvim -S Session.vim : 重新读取一个session,也就读取了所有文件,ft
—————————————-
# 标记(tags) (跳转到subroutines/functions)
taglist.vim : 最流行的插件
:Tlist : 显示Tags (functions的列表)
<C-]> : 跳转到光标处的function
: 这个键 Ctrl-] 和vim帮助中是一样的
—————————————-
# Just Another Vim Hacker J***H
# Juat Another Perl Hacker JAPH,嘿嘿
vim -c “:%s/^/WhfgTNabgureRIvzSUnpxre/|:%s/[R-T]/ /Ig|:normal ggVGg?”
# 译释:呵呵,谁来解释一下吧!
# 其实不过是在激活vim的时候执行了一个命令
# 先写入了 Just Another Vim Hacker 的rot13编码
# 然后再译码
—————————————-

星期三, 11月 21st, 2007

有两个文件:

文件A:

BP00041754,gonet
BP00041784,ajarw
BP00041870,thienlas

文件B:

BP00041754,adfdf,2007/03/17
BP00041754,adffknfa,2007/03/17
BP00041754,jasdjfaj,2007/01/17
BP00041784,ajasdfj,2007/02/13
BP00041870,eruioqt,2007/05/07
BP00041870,jvnza, 2007/03/17

想要合并,变成:

BP00041754,gonet,adfdf,2007/03/17
BP00041754,gonet,adffknfa,2007/03/17
BP00041754,gonet,jasdjfaj,2007/01/17
BP00041784,ajasdfj,ajasdfj,2007/02/13
BP00041870,thienlas,eruioqt,2007/05/07
BP00041870,thienlas,jvnza, 2007/03/17

也就是在文件A中找到key后,将其后面的值插入到文件B中

awk ‘BEGIN{FS=OFS=”,”}NR==FNR{a[$1]=$0}NR!=FNR{if(a[$1]){$1=a[$1]};print}’ fileA fileB

awk的NR和FNR

星期三, 11月 21st, 2007

对于单个文件NR和FNR输出结果一致 

# awk ‘{print NR,$0}’ 1
1 111
2 111

# awk ‘{print NR,$0}’ 1 2
1 222
2 222

相对于多个文件

# awk ‘{print NR,$0}’ 1 2
1 111
2 111
3 222
4 222

# awk ‘{print FNR,$0}’ 1 2
1 111
2 111
1 222
2 222

转shell版俄罗斯方块

星期六, 10月 6th, 2007

#!/bin/bash
# Tetris Game
# 10.21.2003 xhchen<xhchen@winbond.com.tw>

#颜色定义
cRed=1
cGreen=2
cYellow=3
cBlue=4
cFuchsia=5
cCyan=6
cWhite=7
colorTable=($cRed $cGreen $cYellow $cBlue $cFuchsia $cCyan $cWhite)

#位置和大小
iLeft=3
iTop=2
((iTrayLeft = iLeft + 2))
((iTrayTop = iTop + 1))
((iTrayWidth = 10))
((iTrayHeight = 15))

#颜色设置
cBorder=$cGreen
cScore=$cFuchsia
cScoreValue=$cCyan

#控制信号
#改游戏使用两个进程,一个用于接收输入,一个用于游戏流程和显示界面;
#当前者接收到上下左右等按键时,通过向后者发送signal的方式通知后者。
sigRotate=25
sigLeft=26
sigRight=27
sigDown=28
sigAllDown=29
sigExit=30

#七中不同的方块的定义
#通过旋转,每种方块的显示的样式可能有几种
box0=(0 0 0 1 1 0 1 1)
box1=(0 2 1 2 2 2 3 2 1 0 1 1 1 2 1 3)
box2=(0 0 0 1 1 1 1 2 0 1 1 0 1 1 2 0)
box3=(0 1 0 2 1 0 1 1 0 0 1 0 1 1 2 1)
box4=(0 1 0 2 1 1 2 1 1 0 1 1 1 2 2 2 0 1 1 1 2 0 2 1 0 0 1 0 1 1 1 2)
box5=(0 1 1 1 2 1 2 2 1 0 1 1 1 2 2 0 0 0 0 1 1 1 2 1 0 2 1 0 1 1 1 2)
box6=(0 1 1 1 1 2 2 1 1 0 1 1 1 2 2 1 0 1 1 0 1 1 2 1 0 1 1 0 1 1 1 2)
#所有其中方块的定义都放到box变量中
box=(${box0[@]} ${box1[@]} ${box2[@]} ${box3[@]} ${box4[@]} ${box5[@]} ${box6[@]})
#各种方块旋转后可能的样式数目
countBox=(1 2 2 2 4 4 4)
#各种方块再box数组中的偏移
offsetBox=(0 1 3 5 7 11 15)

#每提高一个速度级需要积累的分数
iScoreEachLevel=50        #be greater than 7

#运行时数据
sig=0                #接收到的signal
iScore=0        #总分
iLevel=0        #速度级
boxNew=()        #新下落的方块的位置定义
cBoxNew=0        #新下落的方块的颜色
iBoxNewType=0        #新下落的方块的种类
iBoxNewRotate=0        #新下落的方块的旋转角度
boxCur=()        #当前方块的位置定义
cBoxCur=0        #当前方块的颜色
iBoxCurType=0        #当前方块的种类
iBoxCurRotate=0        #当前方块的旋转角度
boxCurX=-1        #当前方块的x坐标位置
boxCurY=-1        #当前方块的y坐标位置
iMap=()                #背景方块图表

#初始化所有背景方块为-1, 表示没有方块
for ((i = 0; i < iTrayHeight * iTrayWidth; i++)); do iMap[$i]=-1; done
#接收输入的进程的主函数
function RunAsKeyReceiver()
{
        local pidDisplayer key aKey sig cESC sTTY

        pidDisplayer=$1
        aKey=(0 0 0)

        cESC=`echo -ne “\33″`
        cSpace=`echo -ne “\40″`

        #保存终端属性。在read -s读取终端键时,终端的属性会被暂时改变。
        #如果在read -s时程序被不幸杀掉,可能会导致终端混乱,
        #需要在程序退出时恢复终端属性。
        sTTY=`stty -g`
       
        #捕捉退出信号
        trap “MyExit;” INT TERM
        trap “MyExitNoSub;” $sigExit
       
        #隐藏光标
        echo -ne “\33[?25l"

       
        while (( 1 ))
        do
                #读取输入。注-s不回显,-n读到一个字符立即返回
                read -s -n 1 key
               
                aKey[0]=${aKey[1]}
                aKey[1]=${aKey[2]}
                aKey[2]=$key
                sig=0

                #判断输入了何种键
                if [[ $key == $cESC && ${aKey[1]} == $cESC ]]
                then
                        #ESC键
                        MyExit
                elif [[ ${aKey[0]} == $cESC && ${aKey[1]} == “[" ]]
                then
                        if [[ $key == "A" ]]; then sig=$sigRotate        #<向上键>
                        elif [[ $key == "B" ]]; then sig=$sigDown        #<向下键>
                        elif [[ $key == "D" ]]; then sig=$sigLeft        #<向左键>
                        elif [[ $key == "C" ]]; then sig=$sigRight        #<向右键>
                        fi
                elif [[ $key == "W" || $key == "w" ]]; then sig=$sigRotate        #W, w
                elif [[ $key == "S" || $key == "s" ]]; then sig=$sigDown        #S, s
                elif [[ $key == "A" || $key == "a" ]]; then sig=$sigLeft        #A, a
                elif [[ $key == "D" || $key == "d" ]]; then sig=$sigRight        #D, d
                elif [[ "[$key]” == “[]” ]]; then sig=$sigAllDown        #空格键
                elif [[ $key == "Q" || $key == "q" ]]                        #Q, q
                then
                        MyExit
                fi

                if [[ $sig != 0 ]]
                then
                        #向另一进程发送消息
                        kill -$sig $pidDisplayer
                fi
        done
}

#退出前的恢复
function MyExitNoSub()
{
        local y
       
        #恢复终端属性
        stty $sTTY
        ((y = iTop + iTrayHeight + 4))

        #显示光标
        echo -e “\33[?25h\33[${y};0H"
        exit
}
function MyExit()
{
        #通知显示进程需要退出
        kill -$sigExit $pidDisplayer
       
        MyExitNoSub
}
#处理显示和游戏流程的主函数
function RunAsDisplayer()
{
        local sigThis
        InitDraw

        #挂载各种信号的处理函数
        trap "sig=$sigRotate;" $sigRotate
        trap "sig=$sigLeft;" $sigLeft
        trap "sig=$sigRight;" $sigRight
        trap "sig=$sigDown;" $sigDown
        trap "sig=$sigAllDown;" $sigAllDown
        trap "ShowExit;" $sigExit

        while (( 1 ))
        do
                #根据当前的速度级iLevel不同,设定相应的循环的次数
                for ((i = 0; i < 21 - iLevel; i++))
                do
                        sleep 0.02
                        sigThis=$sig
                        sig=0

                        #根据sig变量判断是否接受到相应的信号
                        if ((sigThis == sigRotate)); then BoxRotate;        #旋转
                        elif ((sigThis == sigLeft)); then BoxLeft;        #左移一列
                        elif ((sigThis == sigRight)); then BoxRight;        #右移一列
                        elif ((sigThis == sigDown)); then BoxDown;        #下落一行
                        elif ((sigThis == sigAllDown)); then BoxAllDown;        #下落到底
                        fi
                done
                #kill -$sigDown $$
                BoxDown        #下落一行
        done
}
#BoxMove(y, x), 测试是否可以把移动中的方块移到(x, y)的位置, 返回0则可以, 1不可以
function BoxMove()
{
        local j i x y xTest yTest
        yTest=$1
        xTest=$2
        for ((j = 0; j < 8; j += 2))
        do
                ((i = j + 1))
                ((y = ${boxCur[$j]} + yTest))
                ((x = ${boxCur[$i]} + xTest))
                if (( y < 0 || y >= iTrayHeight || x < 0 || x >= iTrayWidth))
                then
                        #撞到墙壁了
                        return 1
                fi
                if ((${iMap[y * iTrayWidth + x]} != -1 ))
                then
                        #撞到其他已经存在的方块了
                        return 1
                fi
        done
        return 0;
}
#将当前移动中的方块放到背景方块中去,
#并计算新的分数和速度级。(即一次方块落到底部)
function Box2Map()
{
        local j i x y xp yp line

        #将当前移动中的方块放到背景方块中去
        for ((j = 0; j < 8; j += 2))
        do
                ((i = j + 1))
                ((y = ${boxCur[$j]} + boxCurY))
                ((x = ${boxCur[$i]} + boxCurX))
                ((i = y * iTrayWidth + x))
                iMap[$i]=$cBoxCur
        done
       
        #消去可被消去的行
        line=0
        for ((j = 0; j < iTrayWidth * iTrayHeight; j += iTrayWidth))
        do
                for ((i = j + iTrayWidth - 1; i >= j; i–))
                do
                        if ((${iMap[$i]} == -1)); then break; fi
                done
                if ((i >= j)); then continue; fi
       
                ((line++))       
                for ((i = j - 1; i >= 0; i–))
                do
                        ((x = i + iTrayWidth))
                        iMap[$x]=${iMap[$i]}
                done
                for ((i = 0; i < iTrayWidth; i++))
                do
                        iMap[$i]=-1
                done
        done
       
        if ((line == 0)); then return; fi

        #根据消去的行数line计算分数和速度级
        ((x = iLeft + iTrayWidth * 2 + 7))
        ((y = iTop + 11))
        ((iScore += line * 2 - 1))
        #显示新的分数
        echo -ne “\33[1m\33[3${cScoreValue}m\33[${y};${x}H${iScore}         "
        if ((iScore % iScoreEachLevel < line * 2 - 1))
        then
                if ((iLevel < 20))
                then
                        ((iLevel++))
                        ((y = iTop + 14))
                        #显示新的速度级
                        echo -ne "\33[3${cScoreValue}m\33[${y};${x}H${iLevel}        "
                fi
        fi
        echo -ne "\33[0m"
        #重新显示背景方块
        for ((y = 0; y < iTrayHeight; y++))
        do
                ((yp = y + iTrayTop + 1))
                ((xp = iTrayLeft + 1))
                ((i = y * iTrayWidth))
                echo -ne "\33[${yp};${xp}H"
                for ((x = 0; x < iTrayWidth; x++))
                do
                        ((j = i + x))
                        if ((${iMap[$j]} == -1))
                        then
                                echo -ne “  ”
                        else
                                echo -ne “\33[1m\33[7m\33[3${iMap[$j]}m\33[4${iMap[$j]}m[]\33[0m"
                        fi
                done
        done
}
#下落一行
function BoxDown()
{
        local y s
        ((y = boxCurY + 1))        #新的y坐标
        if BoxMove $y $boxCurX        #测试是否可以下落一行
        then
                s="`DrawCurBox 0`"        #将旧的方块抹去
                ((boxCurY = y))
                s="$s`DrawCurBox 1`"        #显示新的下落后方块
                echo -ne $s
        else
                #走到这儿, 如果不能下落了
                Box2Map                #将当前移动中的方块贴到背景方块中
                RandomBox        #产生新的方块
        fi
}

#左移一列
function BoxLeft()
{
        local x s
        ((x = boxCurX - 1))
        if BoxMove $boxCurY $x
        then
                s=`DrawCurBox 0`
                ((boxCurX = x))
                s=$s`DrawCurBox 1`
                echo -ne $s
        fi
}

#右移一列
function BoxRight()
{
        local x s
        ((x = boxCurX + 1))
        if BoxMove $boxCurY $x
        then
                s=`DrawCurBox 0`
                ((boxCurX = x))
                s=$s`DrawCurBox 1`
                echo -ne $s
        fi
}
#下落到底
function BoxAllDown()
{
        local k j i x y iDown s
        iDown=$iTrayHeight

        #计算一共需要下落多少行
        for ((j = 0; j < 8; j += 2))
        do
                ((i = j + 1))
                ((y = ${boxCur[$j]} + boxCurY))
                ((x = ${boxCur[$i]} + boxCurX))
                for ((k = y + 1; k < iTrayHeight; k++))
                do
                        ((i = k * iTrayWidth + x))
                        if (( ${iMap[$i]} != -1)); then break; fi
                done
                ((k -= y + 1))
                if (( $iDown > $k )); then iDown=$k; fi
        done
       
        s=`DrawCurBox 0`        #将旧的方块抹去
        ((boxCurY += iDown))       
        s=$s`DrawCurBox 1`        #显示新的下落后的方块
        echo -ne $s
        Box2Map                #将当前移动中的方块贴到背景方块中
        RandomBox        #产生新的方块
}
#旋转方块
function BoxRotate()
{
        local iCount iTestRotate boxTest j i s
        iCount=${countBox[$iBoxCurType]}        #当前的方块经旋转可以产生的样式的数目

        #计算旋转后的新的样式
        ((iTestRotate = iBoxCurRotate + 1))
        if ((iTestRotate >= iCount))
        then
                ((iTestRotate = 0))
        fi

        #更新到新的样式, 保存老的样式(但不显示)
        for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
        do
                boxTest[$j]=${boxCur[$j]}
                boxCur[$j]=${box[$i]}
        done

        if BoxMove $boxCurY $boxCurX        #测试旋转后是否有空间放的下
        then
                #抹去旧的方块
                for ((j = 0; j < 8; j++))
                do
                        boxCur[$j]=${boxTest[$j]}
                done
                s=`DrawCurBox 0`

                #画上新的方块
                for ((j = 0, i = (${offsetBox[$iBoxCurType]} + $iTestRotate) * 8; j < 8; j++, i++))
                do
                        boxCur[$j]=${box[$i]}
                done
                s=$s`DrawCurBox 1`
                echo -ne $s
                iBoxCurRotate=$iTestRotate
        else
                #不能旋转,还是继续使用老的样式
                for ((j = 0; j < 8; j++))
                do
                        boxCur[$j]=${boxTest[$j]}
                done
        fi
}
#DrawCurBox(bDraw), 绘制当前移动中的方块, bDraw为1, 画上, bDraw为0, 抹去方块。
function DrawCurBox()
{
        local i j t bDraw sBox s
        bDraw=$1

        s=”"
        if (( bDraw == 0 ))
        then
                sBox=”\40\40″
        else
                sBox=”[]”
                s=$s”\33[1m\33[7m\33[3${cBoxCur}m\33[4${cBoxCur}m"               
        fi
       
        for ((j = 0; j < 8; j += 2))
        do
                ((i = iTrayTop + 1 + ${boxCur[$j]} + boxCurY))
                ((t = iTrayLeft + 1 + 2 * (boxCurX + ${boxCur[$j + 1]})))
                #\33[y;xH, 光标到(x, y)处
                s=$s"\33[${i};${t}H${sBox}"
        done
        s=$s"\33[0m"
        echo -n $s
}
#更新新的方块
function RandomBox()
{
        local i j t

        #更新当前移动的方块
        iBoxCurType=${iBoxNewType}
        iBoxCurRotate=${iBoxNewRotate}
        cBoxCur=${cBoxNew}
        for ((j = 0; j < ${#boxNew[@]}; j++))
        do
                boxCur[$j]=${boxNew[$j]}
        done
       

        #显示当前移动的方块
        if (( ${#boxCur[@]} == 8 ))
        then
                #计算当前方块该从顶端哪一行”冒”出来
                for ((j = 0, t = 4; j < 8; j += 2))
                do
                        if ((${boxCur[$j]} < t)); then t=${boxCur[$j]}; fi
                done
                ((boxCurY = -t))