Catalog 目 录
1.grep匹配/etc/services文件中以ftp字符串开头的哪些文本行
9.grep匹配以ftp开头,后跟0个或多个-agent的文本行
10.grep匹配以ftp开头,后跟1个或多个-agent的文本行
11.grep匹配带有数字6,后跟至少3个0的文本行(使用-E启用边界特性)
16.特殊字符:$ . ‘ “ * [ ] ^ | / + ?
22.awk输出至少一个域的所有行。可用来将一个文档里的所有空白行删除
26.awk输出文档的内容时会在每行的最前面输出行号它的功能与'cat -n' 类似
27.awk自定义函数的例子一: 第一个域与第二个域的平方和
39.操作系统和数据库检查(IBM)(一):检查核心参数的配置
43.操作系统和数据库检查(IBM)(五):检查交换区的使用情况
44.操作系统和数据库检查(IBM)(六):检查内存的使用情况
45.操作系统和数据库检查(IBM)(七):检查系统的运行情况
46.操作系统和数据库检查(IBM)(八):检查文件系统的使用情况
47.操作系统和数据库检查(IBM)(九):检查文件系统的属性
49.操作系统和数据库检查(IBM)(十一):检查数据库的DR状态
50.操作系统和数据库检查(IBM)(十二):检查数据库的运行状态
52.操作系统和数据库检查(IBM)(十四):检查数据库的运行日志
1.setenv PATH和set path = (....)
9.shell中确定一个文件的存在,文件ins_billdb
30.iTELLIN示例十四:判断当前用户是否有root权限
32.iTELLIN示例十六:删除某个文件夹下若干天以来未改动的文件
一.shell与Unix平台
Unix平台 | shell |
FreeBSD3.4 | /bin/sh |
SGI IPIX6.5 | /sbin/sh |
HUPX-11 | usr/bin/sh |
UnixWare 7 | $SHELL或/bin/sh |
Solaris 8 (固有的) | /usr/bin/sh |
Solaris 8 (标准的) | /usr/bin/ksh |
IBM AIX 4.3 | /usr/bin/sh |
IBM AIX 4.3 (可信的) | /usr/bin/tsh |
Linux | /bin/sh |
|
|
二.shell基本知识
脚本参数:
shell脚本参数可以任意多,但只有前9各可以被访问,使用shift命令可以改变这个限制。参数从第一个开始,在第九个结束。
$0 程序名字
$n 第n个参数值,n=1..9
$* 所有命令行参数
$@ 所有命令行参数,如果它被包含在引号里,形如”$@”,则每个参数也各自被引号包括
$# 命令行参数个数
$$ 当前进程的进程ID(PID)
$! 最近后台进程的进程ID
$? 最近使用命令的退出状态
其他参数:
$CDPATH 包含一系列目录名,cd命令对他们诸葛进行搜索来查找作为参数传递给它的目录;如果该变量未设置,cd命令搜索当前目录
$EDITOR 程序(如e-mail程序)里使用的默认编辑器
$ENV UNIX查找配置文件的路径
$HOME 用户初次登录时的起始目录名
$MAIL 用户的系统邮箱文件的名称
$MAILCHECK shell检查用户邮箱是否有新邮件并将结果通知用户的间隔时间(以秒为单位)
$PATH 包含用户的搜索路径的变量—shell用来搜索外部命令或程序的目录
$PPID 父进程的进程ID
$PS1 系统第一个提示符,一般为$
$PS2 系统第二个提示符,一般为>
$PWD 当前工作目录的名称
$TERM 用户的控制终端的类型.
$LINENO 所在的代码行,一般用来输出错误行号
shift [n] 将命令行参数往左移n位,但$0不变
export 变量名表 将变量名表所列变量传递给子进程
read 变量名表 从标准输入读字符串,传给指定变量
echo 变量名表 将变量名表指定的变量显示到标准输出
set 显示设置变量
env 显示目前所有变量
set命令可以重新设定参数表.如set hello wold命令会设定$*为字符串hello world,$n和$#也同时受影响。
shift命令可以将所有参数左移一个单位,$*、$n、$#均受影响。
数组(在sh中不支持,可以在ksh中使用):
${#varlist[@]} 数组元素个数
${datalist[index]} 数组元素
${#datalist[index]} 数组元素长度
执行命令:
1) command :直接执行命令command
2) sh command:启动一个shell process执行命令command
3) . command:在本process中执行命令command
4) exec command:本Script将会被所执行的命令所取代,当这个命令执行完毕之後,本Script也会随之结束。
echo 命令使用的特殊字符
/b 退格
/c 显示新行,但是不把光标移到下一行
/f 换页
/n 换行(光标移到下一行)
/r 回车
/t 水平制表符
/v 垂直制表符
// 反斜杠
/ON ASCII码为八进制数N的字符
set命令:
把各位置参数的值依次设为”argument-list”里指定的参数,即重新设置$*,$@,$1-$9
如: set “hello” “world”
则 $*和$@都变成 hello world
$1为hello
$2为world
三.grep 命令
搜索文本的匹配内容。
格式: grep [-option] pattern [filename]
选项:
-c 只输出匹配行的计数
-i 不区分大小写(只适用于单字符)
-h 查询多文件时不显示文件名
-l 查询多文件时只输出包含匹配字符的文件名
-n 显示匹配行及行号
-s 不显示不存在或无匹配文本的错误信息
-v 显示不包括匹配文本的所有行
四.sed
查找和编辑文本。
格式:
直接键入命令
sed [-option] command_line filename
将sed命令插入脚本文件,然后调用sed
sed [-option] -f program_file filename
将sed命令插入脚本文件,并使脚本可执行
sed program_file [-option] filename
选项:
n 不打印;sed不把编辑行写到标准输出,默认为打印所有行(编辑的和未编辑的)。
p命令可以用来打印编辑行。
c 下一个命令是编辑命令。在使用多项编辑时要加入该选项。
f 如果正在调用sed脚本,要使用此选项。此选项sed脚本支持所有的sed命令。
五.awk命令
awk 是一种程序语言,对于资料的处理具有很强的功能,对于文档里的资料做修改、比较、抽取等处理,awk 能够以很短的程序轻易地完成。如果使用C 语言写程序完成上述的操作不方便且很花费时间,所写的程序也会很大。
awk 能够依照用户定义的格式来分解输入的资料也可以依照用户定义的格式来打印资料。
awk 可用于在对象文件中逐行读取记录,按照命令中定义的匹配模式寻找相关记录,然后对该记录进行操作动作。
格式:
(1)直接键入命令:
awk [-Fchar] ‘command_line’ filename
(2)将awk命令插入脚本文件,然后调用awk:
awk -f program_file filename
前一种形式的-Fchar确定间隔符,command_line为操作动作,filename为对象文件。
后一种形式的program_file是指用户按一定格式编制好的对对象文件的匹配与操作。
六.find命令
通过文件名或其它特征查找文件。
格式:
find [path-list] [predicate-list]
选项:
-type tp 文件类型为tp:
b 块特别文件
c 字符设备特别文件
d 目录文件
f 普通文件
p 管道文件(FIFO)
s socket
I 符号链接文件
-user uname 文件属于用户uname。
-group gname 文件属于组gname。
-size n 文件是n块大小(每块512字节),若n后跟一个c,单位为字节。
-atime n 在n天内已访问过此文件。
-mtime n 在n天内已修改过此文件
-ctime n 在n天内文件被修改、属性(拥有者、组、链接数等)被修改。
-exec command {} /; 执行命令
-print 打印当前路径名
-newer file 修改时间比file文件晚
七.test命令
命令格式
test expression
expression中包含一个以上的判断准则以作为test评诂的标准。两准则间用"-a"代 表逻辑AND 运算,"-o"代表逻辑OR运算,而在准则前放置一"!" 代表NOT 运算。如 果没有括号,则优先权则为"!" > "-a" > "-o" 。和expr命令相同,相使用左右括 号时,必须在其前面加上"/" 。
以下是有关准则的叙述(符合叙述时传回真,否则传回伪):
string string不为空白字串
-n string string的长度大於0
-z string string的长度等於0
string1=string2 string1等於string2
string1!=string2 string1不等於string2
int1 -gt int2 int1大於int2
int1 -ge int2 int1大於等於int2
int1 -eq int2 int1等於int2
int1 -ne int2 int1不等於int2
int1 -le int2 int1小於等於int2
int1 -lt int2 int1小於int2
-r filename 档案可读取
-w filename 档案可写入
-x filename 档案可执行
-f filename 档案为一般档
-d filename 档案为目录
-s filename 档案为非空的一般档
test -r "$filename" -a -s "$filename"
八.expr命令
命令格式
expr expression
expression是由字串以及运算子所组成,每个字串或是运算子之间必须用空白隔开 。下表是运算子的种类及功能,而优先顺序则以先後次序排列,可以利用小括号来改变运算的优先次序。其运算结果则输出至标准输出上。
: 字串比较。比较的方式是以两字串的第一个字母开始,而以第二个字串的 字母结束。如果相同时,则输出第二个字串的字母个数,如果不同时则传 回0 。
/| OR运算,如果它非null或者非0,返回第一个表达式,否则返回第二个表达式
/& AND运算,如果非null或非0,返回第一个表达式,否则返回0
=、/>、/>=、/<、/<、!= 整数比较运算符
+、-、/*、/、% 整数算术运算符,其中%求余数。
当expression中含有"*", "(", ")" 等符号时,必须在其前面加上"/" ,以免被 Shell 解释成其它意义。
expr 2 /* /( 3 + 4 /) 其输出为14
if expression
then
[elif expression
then
then-command-list]
. . .
[else
else-command-list]
fi
if-then-fi语句的语义
if-then-else-fi语句的语义
if-then-elif-else-fi语句的语义
4. for语句
for variable [in argument-list]
do
command-list
done
for语句的语义
for var
do
commands
done
例如
for arg
do
echo $var
done
6. while语句
while expression
do
command-list
done
while语句的语义
7. until 语句
until expression
do
command-list
done
until语句的语义
8. break及continue
这两者是用於for, while, until 等循环控制下。break 会跳至done后方执行 ,而continue会跳至done执行,继续执行循环。
9. case 语句
case test-string in
pat1)
command-list1
;;
pat2)
command-list2
;;
. . .
patN)
command-listN
;;
*)
;;
esac
case语句的语义
而pat 除了可以指定一些确定的字串,也可以指定字串的集合,如下
* 任意字串
? 任意字元
[abc] a, b, 或c三字元其中之一
[a-n] 从a到n的任一字元
| 多重选择,如A|a
十.shell脚本调试
1.启动调试
启动调试Shell脚本的基本语法为:
$/bin/sh option script arg1 arg2 ... argN
这里显式声明了要执行脚本的Shell为/bin/sh,script是脚本的名字,arg1到argN是脚本的参数, option为调试选项,如下所示:
-n 读所有的命令,但不执行它们
-v 在读时显示所有的行
-x 在执行时显示所有命令和它们的参数。该选项常称为shell 跟踪选项或
改变脚本的第一行,象下面那样在该行声明一个调试选项:
#!/bin/sh option
2.使用set命令
在每个调用激活调试模式中,调试模式的缺省行为对脚本中从第一行到最后一行都有效。有时我们只需要调试特定的函数或脚本的一部分,这时调试整个脚本就有些多余。通过使用set命令,我们可以在shell脚本的任何地方启动或取消调试,其基本语法为:
set [-|+] option
这里的option选项与上面的相同。
set –x 回显
set –v 详细
如#!/bin/ksh -xv
3.语法检查
在处理任何Shell脚本时,应在准备执行它之前检查脚本的语法,这使我们能改正许多问题。要启动语法检查可使用-n选项,如对于上面的buggy.sh脚本,象下面那样检查语法:
$/bin/sh -n ./buggy.sh
1.ls显示所有以hosts.开头的文件
ls –l hosts.*
2.ls显示包含x,y,z字符的所有文件
ls –d *[x-z]*
1.grep匹配/etc/services文件中以ftp字符串开头的哪些文本行
grep ‘^ftp’ /etc/services
2.grep匹配以system文本结尾的行。
grep ‘system$’ file
3.grep匹配仅包含一个#字符的行。
grep ‘^#$’ file
4.grep匹配以<abc>或者[abc]开头的行
grep ‘[[<]abc[]>]’ file
5.grep匹配以Ftp或者ftp开头的行
grep ‘^[Ff]tp’ file
6.grep匹配F或者f以外的字符
grep ‘[^Ff]’ file
7.grep匹配除大写字符以外的字符
grep ‘[^A-Z]’ file
8.grep匹配以ftp或telnet开头的文本行
grep -E ‘^ftp|^telnet’ file
9.grep匹配以ftp开头,后跟0个或多个-agent的文本行
grep ‘^ftp(-agent)?’ /etc/services
或 grep ‘^ftp(-agent)*’ /etc/services
注:
a)在sco unix下,上面的单括号前要加转义符/
b)在sun os 5.8下,不论加不加单括号均不支持。
10.grep匹配以ftp开头,后跟1个或多个-agent的文本行
grep ‘^ftp(-agent)+’ /etc/services
说明同上。
11.grep匹配带有数字6,后跟至少3个0的文本行(使用-E启用边界特性)
grep -E ‘60/{3,/}’ /etc/services
12.grep匹配含有(abc)的文本
grep ‘/(abc/)’ file
13.常用正则表达式举例
正则表达式 | 匹配功能 |
^[the] | 以the开头行 |
[Ss]igna[lL] | 匹配单词signal,signaL,Signal,SignaL |
[Ss]igna[lL]/. | 同上,但加一个句点 |
[mayMAY] |
|
^USER$ | 只包含USER的行 |
[tty]$ | 以tty结尾的行 |
/. | 带句点的行 |
^d..x..x..x | 对用户、用户组及其它用户组成员有可执行权限的目录 |
^[^l] | 排除关联目录的目录列表 |
[.*0] | 0之前或之后加任意字符 |
[000*] | 000或更多个 |
[iI] | 大写或小写I |
[iI][nN] | 大写或小写I或n |
[^$] | 空行 |
[^.*$] | 匹配行中任意字符 |
^……$ | 包括6各字符的行 |
[a-zA-Z] | 任意单字符 |
[a-z][a-z]* | 至少两个小写字母 |
[^0-9/$] | 非数字或美元表示 |
[^0-9A-Za-z] | 非数字或字母 |
[123] | 1到3中的一个数字 |
[Dd]evice | 单词Device或device |
De..ce | 前两个字母为De,后跟两个任意字符,最后为ce |
^.$ | 仅有一个字符的行 |
^/.[0-9][0-9] | 以一个句点和两个数字开始的行 |
“’Device’” | 单词Device |
De[Vv]ice/. | 单词Device.或DeVice. |
[0-9]/{2/}-[0-9]/{2/}-[0-9]/{4/} | 日期格式dd-mm-yyyy |
[1-9][0-9]/{1,2/}/.[0-9]/{1,3/}/.[0-9]/{1,3/}/.[0-9]/{1,3/} | IP地址格式nnn.nnn.nnn.nnn |
[^.*$] | 匹配任意行 |
14.grep精确匹配:在抽取字符串后加/>。
grep “48/>” file
15.grep消除大小写:加入-i选项
grep -I “sept” file
16.特殊字符:$ . ‘ “ * [ ] ^ | / + ?
如果要查询这些字符,需要在前面加转义字符/。
17.grep判断变量含有[HOST]字符串
if [ "1" -eq "`echo "$VarName" | grep -c '/[HOST/]'`" ]; then
18.grep判断变量含有[xxx]字符串
if [ "1" -eq "`echo "$VarName" | grep -c '/[.*/]'`" ]; then
19.grep匹配后缀为c,h,j,s,cpp,hpp的文件
EXT_ALL='chjs'
EXT_PP='ch'
EXT_NO_PP='js'
ls $1 | grep "/.[$EXT_ALL][p]/{0,2/}$" | grep -v "/.[$EXT_NO_PP][p]/{1,2/}$" | grep -v "/.[$ EXT_PP][p]/{1/}$"
20.使用grep在文件中查找变量
grep `echo $user` /etc/passwd | cut –f5 –d‘:’
21.正则表达式语法
来自msdn,仅供参考。
Here are some examples of regular expressions:
Expression | Matches |
/^/s*$/ | Match a blank line. |
//d{2}-/d{5}/ | Validate an ID number consisting of 2 digits, a hyphen, and an additional 5 digits. |
/</s*(/S+)(/s[^>]*)?>[/s/S]*</s*///1/s*>/ | Match an HTML tag. |
The following table contains the complete list of metacharacters and their behavior in the context of regular expressions:
Character | Description |
/ | Marks the next character as a special character, a literal, a backreference, or an octal escape. For example, 'n' matches the character "n". '/n' matches a newline character. The sequence '//' matches "/" and "/(" matches "(". |
^ | Matches the position at the beginning of the input string. If the RegExp object's Multiline property is set, ^ also matches the position following '/n' or '/r'. |
$ | Matches the position at the end of the input string. If the RegExp object's Multiline property is set, $ also matches the position preceding '/n' or '/r'. |
* | Matches the preceding character or subexpression zero or more times. For example, zo* matches "z" and "zoo". * is equivalent to {0,}. |
+ | Matches the preceding character or subexpression one or more times. For example, 'zo+' matches "zo" and "zoo", but not "z". + is equivalent to {1,}. |
? | Matches the preceding character or subexpression zero or one time. For example, "do(es)?" matches the "do" in "do" or "does". ? is equivalent to {0,1} |
{n} | n is a nonnegative integer. Matches exactly n times. For example, 'o{2}' does not match the 'o' in "Bob," but matches the two o's in "food". |
{n,} | n is a nonnegative integer. Matches at least n times. For example, 'o{2,}' does not match the "o" in "Bob" and matches all the o's in "foooood". 'o{1,}' is equivalent to 'o+'. 'o{0,}' is equivalent to 'o*'. |
{n,m} | M and n are nonnegative integers, where n <= m. Matches at least n and at most m times. For example, "o{1,3}" matches the first three o's in "fooooood". 'o{0,1}' is equivalent to 'o?'. Note that you cannot put a space between the comma and the numbers. |
? | When this character immediately follows any of the other quantifiers (*, +, ?, {n}, {n,}, {n,m}), the matching pattern is non-greedy. A non-greedy pattern matches as little of the searched string as possible, whereas the default greedy pattern matches as much of the searched string as possible. For example, in the string "oooo", 'o+?' matches a single "o", while 'o+' matches all 'o's. |
. | Matches any single character except "/n". To match any character including the '/n', use a pattern such as '[/s/S]'. |
(pattern) | A subexpression that matches pattern and captures the match. The captured match can be retrieved from the resulting Matches collection using the $0…$9 properties. To match parentheses characters ( ), use '/(' or '/)'. |
(?:pattern) | A subexpression that matches pattern but does not capture the match, that is, it is a non-capturing match that is not stored for possible later use. This is useful for combining parts of a pattern with the "or" character (|). For example, 'industr(?:y|ies) is a more economical expression than 'industry|industries'. |
(?=pattern) | A subexpression that performs a positive lookahead search, which matches the string at any point where a string matching pattern begins. This is a non-capturing match, that is, the match is not captured for possible later use. For example 'Windows (?=95|98|NT|2000)' matches "Windows" in "Windows 2000" but not "Windows" in "Windows 3.1". Lookaheads do not consume characters, that is, after a match occurs, the search for the next match begins immediately following the last match, not after the characters that comprised the lookahead. |
(?!pattern) | A subexpression that performs a negative lookahead search, which matches the search string at any point where a string not matching pattern begins. This is a non-capturing match, that is, the match is not captured for possible later use. For example 'Windows (?!95|98|NT|2000)' matches "Windows" in "Windows 3.1" but does not match "Windows" in "Windows 2000". Lookaheads do not consume characters, that is, after a match occurs, the search for the next match begins immediately following the last match, not after the characters that comprised the lookahead. |
x|y | Matches either x or y. For example, 'z|food' matches "z" or "food". '(z|f)ood' matches "zood" or "food". |
[xyz] | A character set. Matches any one of the enclosed characters. For example, '[abc]' matches the 'a' in "plain". |
[^xyz] | A negative character set. Matches any character not enclosed. For example, '[^abc]' matches the 'p' in "plain". |
[a-z] | A range of characters. Matches any character in the specified range. For example, '[a-z]' matches any lowercase alphabetic character in the range 'a' through 'z'. |
[^a-z] | A negative range characters. Matches any character not in the specified range. For example, '[^a-z]' matches any character not in the range 'a' through 'z'. |
/b | Matches a word boundary, that is, the position between a word and a space. For example, 'er/b' matches the 'er' in "never" but not the 'er' in "verb". |
/B | Matches a nonword boundary. 'er/B' matches the 'er' in "verb" but not the 'er' in "never". |
/cx | Matches the control character indicated by x. For example, /cM matches a Control-M or carriage return character. The value of x must be in the range of A-Z or a-z. If not, c is assumed to be a literal 'c' character. |
/d | Matches a digit character. Equivalent to [0-9]. |
/D | Matches a nondigit character. Equivalent to [^0-9]. |
/f | Matches a form-feed character. Equivalent to /x0c and /cL. |
/n | Matches a newline character. Equivalent to /x0a and /cJ. |
/r | Matches a carriage return character. Equivalent to /x0d and /cM. |
/s | Matches any white space character including space, tab, form-feed, and so on. Equivalent to [ /f/n/r/t/v]. |
/S | Matches any non-white space character. Equivalent to [^ /f/n/r/t/v]. |
/t | Matches a tab character. Equivalent to /x09 and /cI. |
/v | Matches a vertical tab character. Equivalent to /x0b and /cK. |
/w | Matches any word character including underscore. Equivalent to '[A-Za-z0-9_]'. |
/W | Matches any nonword character. Equivalent to '[^A-Za-z0-9_]'. |
/xn | Matches n, where n is a hexadecimal escape value. Hexadecimal escape values must be exactly two digits long. For example, '/x41' matches "A". '/x041' is equivalent to '/x04' & "1". Allows ASCII codes to be used in regular expressions. |
/num | Matches num, where num is a positive integer. A reference back to captured matches. For example, '(.)/1' matches two consecutive identical characters. |
/n | Identifies either an octal escape value or a backreference. If /n is preceded by at least n captured subexpressions, n is a backreference. Otherwise, n is an octal escape value if n is an octal digit (0-7). |
/nm | Identifies either an octal escape value or a backreference. If /nm is preceded by at least nm captured subexpressions, nm is a backreference. If /nm is preceded by at least n captures, n is a backreference followed by literal m. If neither of the preceding conditions exists, /nm matches octal escape value nm when n and m are octal digits (0-7). |
/nml | Matches octal escape value nml when n is an octal digit (0-3) and m and l are octal digits (0-7). |
/un | Matches n, where n is a Unicode character expressed as four hexadecimal digits. For example, /u00A9 matches the copyright symbol (©). |
三.sed命令
sed的正则表达式用//括住。
1.sed文本的定位方法:
x | x为一行号 |
x,y | 表示行号范围从x到y |
/pattern/ | 查询包含模式的行 |
/pattern/pattern/ | 查询包含两种模式的行 |
/pattern/,x | 在给定行号上查询包含模式的行 |
x,/pattern/ | 通过行号和模式查询匹配行 |
x,y! | 查询不包括指定行号x和y的行 |
2.sed编辑命令
命令 | 意思 |
p | 打印匹配行 |
= | 显示文件行号 |
a/ | 在定位行号后附加新文本信息 |
i/ | 在定位行号后插入新文本信息 |
d | 删除定位行 |
c/ | 用新文本替换定位文本 |
s | 使用替换模式替换相应模式 |
r | 从一个文件中读文本 |
w | 将文本写道一个文件 |
q | 第一个模式匹配完成以后退出或立即退出 |
l | 显示八进制ASCII代码等价的控制字符 |
{} | 在定位行执行的命令组 |
n | 从另一个文件中读文本下一行,并附加到下一行 |
g | 将模式2粘贴到/pattern n/ |
y | 传送字符 |
3.sed打印文件的第二行
sed -n ‘2p’ filename
4.sed打印文件的第一到三行
sed -n ‘1,2p’ filename
5.sed打印匹配test的行
sed -n ‘/test/p’ filename
6.sed打印匹配$的行
sed -n ‘//$/p’ filename
7.sed打印最后一行:$是代表最后一行的特殊字符
sed -n ‘$p’ filename
8.sed脚本文件
#!/bin/sed –f “/company/” a/ “The suddenly it happen.”
将以上脚本保存为append.sed,使用chmod给予其可执行权限。使用append.sed filename运行。脚本的执行将会在filename文件中查找company,在匹配行的后一行中附加新文本,输出到屏幕上(不改变原文件)。
9.sed上例中
如果将a/改为i/:则为插入,在匹配行的前一行中附加新文本,输出到屏幕(不改变原文件)。
10.sed上例中
如果将a/改为c/:则为替换,匹配行被替换为新文本。
11.sed删除第一行
sed ‘1d’ filename
12.sed删除第一到第三行
sed ‘1,3d’ filename
13.sed删除最后一行
sed ‘$d’ filename
14.sed替换文本
sed ‘s/night/NIGHT/’ filename #将所有night替换为NIGHT
sed ‘s/night//’ filename #将night删除
15.sed输出到文件,w选项:
把第1到2行的内容输出到文件field中,不存在则创建。
sed ‘1,2w field’ filename
16.sed从文件读取,r选项:
把文件内容附加到匹配行company.之后
sed ‘/company./r sedex.txt’ filename
17.sed优势:
用户在获得不同格式的、带有各种奇形怪状格式控制符的文本,需要将它编成易读的文本时,就可以使用sed流编辑程序。另外,在重新处理具有比较固定格式的文本以生成新格式的文本时,也可以使用sed流编辑程序。
18.sed常见的一行命令集
命令 | 意思 |
‘s//.$//g’ | 删除以句点为结尾行 |
‘-e/abcd/d’ | 删除包含abcd的行(疑为’/abcd/d’) |
‘s/[ ][ ]*/[ ]/g’ | 删除一个以上空格,用一个空格代替 |
‘s/^[ ][ ]*//g’ | 删除行首空格 |
‘s//.[ ][ ]*/[]/g’ | 删除句点后跟两个或多个空格,用一个空格代替 |
‘s/^$/d’ | 删除空行(sh不支持d,但在ksh下支持) |
‘s/^.//g’ | 删除第一个字符 |
‘s/COL/(…/)//g’ | 删除COL以及其后的三个字母 |
‘s/^g’ | 删除开头的/ |
‘s/[ ]*/[ ]/g’ | 删除所有空格并用tab代替 |
‘s/^[ ]//g’ | 删除行首的一个tab |
‘s/^[ ]*//g’ | 删除行首的所有tab |
‘s/[ ]*//g’ | 删除所有tab |
‘s/[ ]*/[ ]/g’ | 删除所有tab并用一个空格代替 |
‘s/[ ][ ][ ][ ]*/[ ]/g’ | 每四个空格删除并使用一个tab代替 |
19.sed去掉字串变量前后的空格
str1=” 1234 “
str2=` echo ${str1} `
此时str2不含有前后的空格。
如果使用sed如下:
str2=”` echo ${str1} | sed ‘s/^[ ]*//g’ | sed ‘s/[ ]*$//g’ `”
如果使用awk如下:
str2=”` echo $(str1) | awk ‘{print $1}’`”
或:
str2=”` echo ${str1} | sed ‘s/(^/s*) | (/s*$)//g’ `”
注:使用awk和sed的缘故是可以和前一次的操作一次性完成,而不必单独使用一条语句去除空格。例如下面第二个awk的作用就是去除空格:
TmpInf1="`echo $TmpInf | awk -F= '{print $2}' | awk '{print $1}'`"
20.sed去除文件count中的前后的空格
tmp=`sed 's/^ *//g' count | sed 's/ *$//g' `
则tmp为文件内容,不含有前后的空格。
21.sed提取最后一个目录名和程序名
例如从../../etc/passwd或者/etc/passwd得到passwd
方法一:使用临时文件
#得到当前路径,输出到a文件
pwd >a
#读取a文件,过滤首字母/和尾字母/,将结果输出到b文件
sed 's/^g' a | sed ‘s///$//g’ >b
while fgrep // b
do
#读取b文件,过滤首字符串xxxx/,将结果输出到a文件
sed 's/^[a-zA-Z0-9]*g' b >a
#将a文件拷贝到b文件
cp -f a b
done
rm –f a
rm –f b
方法二:使用变量(优于文件形式)
c_path=`pwd`
#过滤首字母/和尾字母/
c_path=`echo $c_path | sed 's/^g' | sed ‘s///$//g’ `
while [ `echo $c_path | grep -c '//'` -gt 0 ]
do
c_path=`echo $c_path | sed 's/^[a-zA-Z0-9_.]*g'`
done
echo $cur_path
方法三:使用basename命令
c_path=`pwd`
c_path=`basename $c_path`
注:参数扩展见五.5
22.dirname或参数扩展提取目录名
例如从$0参数中提取运行的路径:从../../etc/passwd/得到../../etc,从/etc/passwd得到/etc
方法一:dirname
c_path=$0
c_path=`dirname $c_path`
注:如果没有路径,则c_path得到为单字符”.”。所以,判断是否在当前路径执行可以使用条件 “-$c_path” = “-.”
方法二(参数扩展在基本sh下不支持):
c_path=$0
c_path=’${0%/*}’
注:如果没有路径,则c_path得到为文件名,即$0。所以,判断是否在当前路径执行可以使用条件 “-$c_path” = “-$0”
23.grep,sed获取文件的扩展名
例如从../../home/file.c得到c
方法一:
file=$1
#得到最后一级文件名 ,如file.c
file=`basename $file`
#如果文件名中不含有.,则表示没有后缀
if [ 1 -gt `echo $file | grep -c '/.'` ]; then
echo "no extion"
else
#过滤掉最后一个.以及之前的所有字符,得到扩展名
echo `echo $file | sed "s/.*/.//g" `
fi
方法二:(参数扩展在基本sh下不支持)
file=$1
#得到最后一级文件名 ,如file.c
file=`basename $file`
#从file的尾部开始删除匹配.*(一个.后跟若干字符)的最小部分并返回剩余部分
echo "${file%.*}"
24.sed获取第n个匹配的行的行号
get_match_line_no()
{
n=$1 #第n个匹配的行
file=$2 #要搜索的文件
str=$3 #要匹配的字符串
sed -n "/${str}/=" ${file} | sed -n "${n}p"
}
注:
若仅仅想匹配第一个,可以用一个sed完成
sed -n '/include/ {
=
q }' print.cpp
其中: =表示打印行号, q标识匹配第一个就退出。
四.awk命令
1.awk字段分隔符:
-F选项指定了字段分隔符为冒号
awk -F: ‘{print $1,$3}’ file
2.awk匹配模式
分为三类:
a) awk的关系表达式:
用来说明字段是否与要求符合。例如:$1==”char” 、$2>20等等。
b) awk的正则表达式:
用//括住。规则与sed相同。
例如:
/^.$/ 匹配只有一个字符的行。
c) awk的BEGIN和END模式:
BEGIN模式意味着在读取第1行之前的匹配模式。它常用于初始化,例如设置分隔符、打印标题以及变量赋初值等。END模式是在处理完所有记录行以后的匹配模式。它常常用于输出结果。
3.awk“模式匹配-动作”
a)在每一行中匹配’foo’,若匹配则打印该行
awk ‘/foo/ {print $0}’ filename
b)在每一行中匹配第一个字段是否为’foo’, 若匹配则打印该行
awk ‘$1~/foo/ {print $0}’ filename
4.awk内部变量
(部分变量需要验证)
变量 | 含义 | 默认值 | 属性 |
ARGC | 命令行实参个数 | - | 只读 |
ARGV | 命令行实参数组 | - | 可读可写 |
FILENAME | 当前输入文件名 | - | 只读 |
FNR | 当前文件中的记录数 | - | 只读 |
FS | 输入字段分隔符 | 空白及制表符 | 可读可写 |
NF | 当前记录中的字段数 | - | 只读 |
NR | 至今读取的记录数 | - | 只读 |
OFMT | 数的输出格式 | %.6g | 可读可写 |
OFS | 输出字段分隔符 | 空白 | 可读可写 |
ORS | 输出记录分隔符 | 换行符 | 可读可写 |
RS | 输入记录分隔符 | 换行符 | 可读可写 |
RSTART | 由match()匹配的第一个字符索引 | - | 只读 |
RLENGTH | 由match()匹配的串的长度 | - | 只读 |
SUBSEP | 下标分隔符 | “/34” | 只读 |
CONVFMT | 数值的内部转换格式 | %.6g | 可读可写 |
5.awk用户定义变量
用户自定义变量用以存放数据以及进行运算。
6.awk算术运算
算术运算在内部以浮点形式完成,也包含一般的加、减、乘、除、余和乘幂,运算符分别为”+”、”-“、”*”、”/”、”%”和”^”。
awk ‘$1==”Feb” {sum=$2+$3} END{print sum}’ filename
awk ‘$1==”ATOM” {a=a+$2;i=i+1}’ filename
7.awk高级算符
++或者+=等等。
awk ‘$1==”ATOM” {a+=$2;i++}’ filename
8.awk内部算术函数
函数名 | 返回值 |
cos(x) | x的余弦值,x是弧度 |
exp(x) | x的幂函数 |
int(x) | x的整数部分 |
log() | x的自然对数 |
rand() | 得出一个随机数,此随机数平均分布在0 和1 之间。这个值不会是0,也不会是1。 每次执行awk, rand 产生相同的随机数序列。 |
sin(x) | x的正弦值,x是弧度 |
sqrt(x) | x的平方根 |
srand(x) | x是针对rand()的新的种子。设定产生随机数的开始点或seed 随机数种子为x。如果在第二次你设定相同的seed 值,你将再度得到相同序列的随机数如果省略参数x,则现在的日期时间会被当成seed。这个方法可使得随机数是真正不可预测的srand 的。 返回值(return value)是前次所设定的seed 值 |
9.awk内置函数
awk的字符串使用引号括起。通过连接常量、变量、数组元素、函数和其它表达式可以创建串表达式。
例如:打印第几号记录和一个冒号,然后打印文本行。
{print NR”:”$0}
函数名 | 返回值 |
gsub(r,x) | 在当前记录中,用s替换r,返回替换数 |
gsub(r,s,t) | 在串t中,用s替换r,返回替换数 |
index(s,t) | 返回s串中t的位置,不出现时为0 |
length(s) | 返回s的长度 |
match(s,r) | 返回r在s中出现的位置,不出现时为0 |
split(s,a) | 针对FS把s分成数组a,返回字段数 |
split(s,a,r) | 针对r把s分成数组a,返回字段数 |
sprintf(fmt,expr_list) | 根据格式串fmt返回经过格式编排的expr_list |
sub(r,s) | 在当前记录中把第一个r替换成s,返回替换数 |
sub(r,s,t) | 在t中把第一个r替换成s,返回替换数 |
substr(s,p) | 返回从位置p开始的s的后缀 |
substr(s,p,n) | 返回从位置p开始长度为n的s子串 注: p最小为1,当p为0时,p被置为1; n个字符包括p所在字符。 |
system(cmd) | 执行命令并返回出口状态 |
toupper(s) | 将输入参数s中的字符全部转换为大写字符并返回转换后的字符串 |
tolower(s) | 将输入参数s中的字符全部转换为小写字符并返回转换后的字符串 |
close( expr ) | 关闭由expr表示的文件或管道,文件或管道可能被print、printf语句或调用内建函数getline打开。如果成功,函数返回0,否则返回非0值 |
getline | 这个内建函数将$0设置为当前输入文件的下一个输入记录,getline < file将用从file中获得下一条记录修改$0的值,getline x用下一行的内容替换变量x,而$0仍然是当前行的内容。但下一次返回的将是下下一行的内容。cmd | getline将从管道中获得cmd命令的输出。如果成功,getline返回1,遇到文件结尾,getline返回0,出错返回-1。 |
|
|
10.awk的自定义函数
格式:
function func_name(arg_list)
{
}
例如:
将下列代码保存在awk_pro文件中,调用echo 5 | awk –f awk_pro,将得到输出:5!is120。
function fact(n)
{
if(n<=1)
return 1
else
return n*fact(n-1)
}
{print $1”!is” fact($1)}
数组实参可以通过应用传递,所以针对该函数有可能改变数组元素或创建一个新元素。标量实参将用值传递,形式参数是局部变量,但其它变量都是全局量。
11.awk的“下一”语句:
next 语句 、next file 语句 、 exit 语句
next语句强迫awk立刻停止处理目前的记录而继而处理下一个记录。
next file类似next,它强迫awk立刻停止处理目前的数据文件而继而处理下一个文件。
exit语句会使得awk程序停止执行而跳出。如果END出现,它会去执行END的动作。
12.awk中的字符串相加:
str3为str + str2 + str
str="hello""world"
str2="----- "
str3=str str2 str
13.awk的逻辑运算符
表达式 | 含义 |
x==y | x等于y时为真 |
x>y | x大于y时为真 |
x>=y | x大于或等于y时为真 |
x<y | x小于y时为真 |
x<=y | x小于或等于y时为真 |
x!=y | x不等于y时为真 |
x~y | x包含y时为真 |
x!~y | x不包含y时为真 |
|
|
例如:
awk '$2~"aaa" {print $0}' filename
14.awk的逻辑与||、逻辑或&&
awk '$2=="bbb" || $2=="ccc" {print $0}' filename
awk '/2400/ && /foo/' BBS-list
awk '/2400/ || /foo/' BBS-list
awk '!/foo/' BBS-list
15.awk的FS、OFS和ORS使用:
以’|’为分隔符输出各个域
awk ‘BEGIN{OFS=”|”}{print $1,$2,$3,$4}’ filename
awk 'BEGIN {OFS=";"; ORS="/n/n"} {print $1, $2}' filename
awk 'BEGIN {FS=","}; {print $2}'
16.awk的sprintf函数的使用
sprintf格式化字符串
print sprintf("%03d", 2);
17.awk的重定向,输出到文件:
可以使用>或者>>
print "This is a test" > "fff.txt"
18.awk删除文件的第一行
awk ‘{ if (NR % 2 == 1) printf “%s”, $0 ’
19.awk删除输入行中特定行的换行字符
例如:删除奇数行的换行字符
awk '
{
if (NR % 2 == 1)
printf "%s",$0 ;
else
print $0
}'
20.awk获取输入行中,域的最大个数
awk '{if (NF > max) max = NF} END {print max}'
21.awk输出一行超过80 个字符的每一行
awk 'length($0) > 80'
22.awk输出至少一个域的所有行。可用来将一个文档里的所有空白行删除
awk '{if (NF > 0) print}'
23.awk输出范围在0 到100 之间的7 个随机数
awk 'BEGIN {for (i = 1; i <= 7; i++)
print int(101 * rand())}'
24.awk将所有用户的login名称依照字母的顺序输出
awk 'BEGIN {FS = ":"} {print $1 | "sort"}' /etc/passwd
25.awk将一个文档的总行数输出
awk '{nlines++} END {print nlines}'
或awk 'END {print NR}'
26.awk输出文档的内容时会在每行的最前面输出行号它的功能与'cat -n' 类似
awk '{print NR,$0}'
27.awk自定义函数的例子一: 第一个域与第二个域的平方和
awk ‘{print "sum =",SquareSum($1,$2)}
function SquareSum(x,y)
{
sum=x*x+y*y
return sum
}’
28.awk的split、数组、注释
test.awk 文件:
#!/bin/awk -f
BEGIN
{
record="123#456#789"
num=split(record,myarray,"#")
}
END
{
for(i=1;i<=num;i++)
{
print myarray[i] # print the element of array
}
}
调用:
./test.awk /dev/null
输出:
123
456
789
29.awk打印传入字符串的第n个分隔域。
str是字符串,num定义了要打印的域的序号。
str=”abc bcd cde efg”
num=2
echo "$num $str" | awk '{k=$1+1; print $k}'
打印出:
bcd
注:k的值是$1+1而不是$1,因为$num也要算awk的传入参数。
30.在awk中使用shell中的变量
str1="hello world"
str2="world"
echo "$str1" | eval "awk '{
if(/$2==/"$str2/")
print(/"$str1/")
}'"
打印
hello world
另一种方法就是把shell中的变量当参数通过管道传入到awk中。
需求:
已知变量 usr的值为 sms, 要求使用 awk 在 /etc/passwd文件中查找(以:为分隔符号), 当匹配到第一个域(name)时,打印第6个域(home).
所需表达式:
awk –F: ‘{ if($1==”sms”) print $6 }’ /etc/passwd
#!/bin/ksh
#set -x
usr="sms"
# 方法一,使用临时文件 tmp.txt
eval "awk -F: '{ if (/$1==/"$usr/") print /$6 }' /etc/passwd >tmp.txt"
cat tmp.txt
# 方法二,完全使用eval合成
par1='/$1'
par6='/$6'
equal='/"'
eval "cmd=/" awk -F: '{ if ( $par1==$equal$usr$equal ) print $par6 }' /etc/passwd /""
#echo "cmd:$cmd"
home=`eval "$cmd" `
echo $home
注:
(1) eval 按照双引号进行展开, 每一对双引号展开一次, 我们例子中的句子:
eval "cmd=/" awk -F: '{ if ( $par1==$equal$usr$equal ) print $par6 }' /etc/passwd /""
awk中引用的变量被两对双引号包括,所以要构造出所需表达式,需要保证$1和”能将禁得起两次展开:
二次展开定义式:
par1=’/$1’ # 单引号
在两次展开以后就变成了$1
二次展开定义式:
equal=’/”’ # 单引号
在两次展开以后就变成了”
由于希望$usr在两次展开之后变成 sms, 所以不需要二次展开定义式,如下定义式:
usr="sms"
在两次展开以后就变成了sms
(2) 当合成cmd以后, 会发现cmd已经合成为:
cmd: awk -F: '{ if ( $1=="sms" ) print $6 }' /etc/passwd
但是不能调用
home=`$cmd`
来获取其输出值 ,而只能使用
home=`eval "$cmd" `
方法三(推荐用法):
使用 awk –v参数.
awk –F: -v usr="$usr" ‘{ if ($1==usr) rint $6 }’ /etc/passwd
注:如果有多个参数需要共享,可以使用多个-v参数传入.
其它实现的方法:
# 方法四: 查找以 $usr: 开头的行,打印第6个元素
home=`cat /etc/passwd | grep "^$usr:" | awk -F: '{ print $6 }'`
echo $home
# 方法五: 重新组织行,将要查找的字符串放到首位,各个字符串以空格分隔, 然后查找以 $usr 开头的行,打印相应元素.
# 此方法适用于不以要查找的字符串为开头的行, 重新组织以后,就可以使用方法四.
home=`cat /etc/passwd | awk -F: '{ printf("%s %s/n",$1,$6) }' | grep "^$usr" | awk '{print
$2 }' `
echo $home
31.在某个目录下查找包含特定字符串的文件。返回文件名称
dir="/opt/informix/*"
find_str="config"
grep -c "$find_str" "$dir" | awk 'BEGIN{FS=":"}{ print $1 }'
返回找到文件的列表,每行一个文件。
1.eval命令:可用于动态生成和执行代码
foo=10
x=foo
eval y=’$’$x
echo $y
输入10,即eval y=’$’$x被解释为y=$foo,即y=10。
nDay1="111"
nDay2="222"
nDay3="333"
# 遍历变量nDay1 ...nDay3,打印其值
for i in 1 2 3
do
n=$i
eval nVar='$nDay'$i
echo $nVar
done
应该依次输出 $nDay1 , $nDay2, $nDay3 ,即:
111
222
333
另一个用于数组的例子,
#!/bin/ksh
nDay_1[0]=""
nDay_2[0]=""
nDay_3[0]=""
k=2
for i in 1 2 3
do
eval "nDay_$i[$k]=$i" # 赋值, 型如:nDay_x[n]=$i
eval "nVar=/${nDay_$i[$k]}" # 访问, 型如:nVar=${nDay_x[n]}
echo ${nVar} # 打印
done
应该依次输出 ${nDay_1[2]}, ${nDay_2[2]}, ${nDay_3[2]}, 即:
1
2
3
2.exit n:退出
0代表成功,1-125代表出错代码,128以上引发一个信号。
我们脚本或许会和别的脚本交互,这个时候需要相互传递信息,exit是被调用进程的返回值,调用进程使用$?获得返回值。
注:exit和return不同,return用于函数返回值,调用函数和被调用函数在同一个进程中,获取返回值都是用$?。
3.export导出环境变量:
把参数变量名导出到子shell里,使之成为子shell的环境变量。
存在a.sh和b.sh两个shell脚本,在a.sh中调用b.sh,a.sh使用export输出的变量将成为b.sh的环境变量。
使用set –a 或者set –allexport将把在它之后声明的任何变量导出为环境变量。
csh中使用setenv来设置变量。
4.shift命令:
把所有参数变量向左移动一个位置,但$0不变。每次执行shift,则参数变量左移一个位置,$1变成$2,$2变成$3,...,最右边的那个参数变为空。
while [ "$1" != "" ];
do
echo "$1"
shift
done
若用户参数为 –m -n -z
则上述代码依次输出 :
–m
-n
-z
5.shell的参数扩展:
tmp_1="1111"
tmp_2="2222"
for i in 1 2
do
eval tmp='$'tmp_${i}
echo $tmp
done
其中,tmp_${i}为参数扩展的应用。常见参数扩展替换见下表:
参数扩展 | 说明 |
${param:-default} | 若param空,则把它设为default的值 |
${#param} | 给出param的长度 |
${param%word} | 从param的尾部开始删除匹配word的最小部分并返回剩余部分(sh不支持,ksh支持) |
${param%%word} | 从param的尾部开始删除匹配word的最大部分并返回剩余部分(sh不支持,ksh支持) |
${param#word} | 从param的头部开始删除匹配word的最小部分并返回剩余部分(sh不支持,ksh支持) |
${param##word} | 从param的头部开始删除匹配word的最大部分并返回剩余部分(sh不支持,ksh支持) |
例:将某个文件夹下所有gif文件通过cjpeg程序转换为jpeg文件。
for image in *.gif
do
cjpeg $image > $(image%%gif)jpg
done
例如:
FILE_NAME=${0##*/} 程序的文件名(不带路径)
BASE_DIR=${0%/*} 程序的路径
其它实例可参见三.22
6.<<即时文档
开始是”<<”,然后是特殊字符序列,该序列将在文档结尾再次出项。注意,结束的!FUNKY!最好顶格,前后不要留空格。
cat <<!FUNKY!
hello
this is a here
!FUNKY!
7.sh调试选项
使用”-o”设置选项,使用”+o”取消设置。
命令行选项 | set命令选项 | 说明 |
sh -n <script> | set -o noexec | 只检查语法错误,不执行命令 |
set -n | ||
sh -v <script> | set -o verbose | 在执行命令之前回显它们 |
set -v | ||
sh -x <script> | set -v xtrace | 在处理完命令行之后回显它们 |
set -x | ||
set -o nounset | 如果使用了未定义变量 就给出一条出错信息 | |
| ||
|
|
|
8.time命令测试一个程序执行时间
time test.sh
9.expr命令
x=`expr 10 + 10`
x=`expr $x + 10`
x=`expr $ /* 2 `
注:加号两边必须有空格,乘号必须有转义符。
10.if语句判断变量是否为某个值(防止空串)
因为数值的比较操作数不能为空,所以如果变量可能为空,且仅仅是进行等于或者不等于的比较操作时,则应转化为:
if [ "-$VarName" = "-5" ]; then
而不要使用 if [ $VarName –eq 5 ]; then
数值测试有如下比较符:
-eq 、-ne、-gt、-lt、-le、-ge
对于-gt 、-lt、 -le 、 -ge等其他比较符,有以下两种方法:
a) 先判断是否为空,然后再做比较(适用于确定变量为数字的情况)
b) 先判断为数字,然后再做比较(适用于不确定变量为数字的情况)。
if ["-$VarName" != "-" ]; then
if [ $VarName –gt 5 ]; then
......
或者
is_integer $VarName
if [ $? = 0 ] ; then
if [ $VarName –gt 5 ]; then
......
注:is_integer函数判断一个串是否是整数,见章节“六.31 iTELLIN示例十五”
11.nm命令察看一下xxx.o文件中是否有多个相同名字的函数
12.ps、grep和awk显示属于某个用户的所有进程(并杀死)
方法一:ps + grep
list=ps -e -f | grep USRID
方法二:ps -u
list=`ps -u $LOGNAME`
方法三(推荐)ps + grep + awk:
list=`ps -u $LOGNAME|grep -v csh|grep -v PID|awk '{print $1}'`
说明:
grep –v csh 避免杀死本sh程序(也有可能遗漏一些sh程序)
grep –v PID 由于ps显示有顶行标题,此句可以过滤此行
杀死程序:
for i in $list
do
kill -9 $i
done
13.touch命令
创建以当前时间为文件名的文件:
touch logfile.`date ’+%y%m%d.%H:%M’`
创建修改时间为1996年1月2日03:04的文件:
touch 0102030496 file
注:用两位数字表示年份,2003写作03,1996写作96
14.touch与make联合使用强制编译
touch *.c
make
make将发现所有的.c文件都比相应的.o文件具有更新的版本,从而重新编译。
15.dd命令传送文件
使用 dd指令,可以把一个文件转换成另一个文件,也可以选择文件的一部份传输,在传输的数据中,也可以交换字节顺序。
dd if=/dev/fd0 of=/temp/save skip=5 count=6 bs=5k
上面的指令″/dev/fd0″ 是指电脑上的软盘,″skip=n″代表在复制到输出文件之前,跳过输入文件上的几个记录。″bs=n″则 表示设置输入输出字节块长度,用 k 表示 1024 字节。″count=n″ 只复制输入记录的指定数,所以上述指令跳过25k字节,拷贝30k字节。
16.talk命令
与本机用户交谈
talk user_name
与在ccsun22主机上的用户交谈
talk user_name@ccsun22
17.ps命令
-u 〈username〉选项显示指定用户的讯息。
-t 〈ttynamt〉选项显示指定终端有关的进程讯息。
而ps -elf指令则提供了需有F、S、C、PRI、NI、TIME字段的使用讯息:
F是指示进程位置,20表示在内存,0表示交换在盘上, 31是系统进程。
S是指示进程状态,睡眠还是正在运行。
C是进程占有CPU的百分率
TIME是花费CPU的总时间。
PRI是进程当前优先数
NI是进程的nice (ADM)菜单
18.rm指令
-i 征求确认后才会删除
-r <目录> 删除该目录及该目录之下的所有档案
-rf <目录> 同上,但不会先徵求确认
19.find命令
在/usr/ice下查找hihi.c文件或目录,找到后在屏幕上显示
find /usr/ice -name hihi.c -print
20.df命令
显示可使用之档案储存空间及档案数目
df
21.rusers命令
rusers命令列出远程机器上的用户
列出网络上各台主机的用户
rusers
列出sco-gfep主机上的用户
rusers -l sco-gfep
-l选项以who的格式给出一个表(较详细)
22.cal命令
显示2003年年历
cal 2003
显示本月月历
cal
显示2003年九月月历
cal 09 2003
23.tty命令
显示目前所用终端机名称
24.banner命令
放大显示字符(个数不超过10个):
banner “1234”
25.find命令
find . -name hello -print 寻找目前目录及所有的子目录内叫hello的文件
find . -size +2000m -print 找出大小超过2000 bytes的档案
find /tmp -user b1234567 -print 在/tmp下属於b1234567的档案
find . -name '*.c' -exec rm {} /; 删除所有的.c档
find . –mtime +6 –print 找出修改时间在6天前的档案
find . -ctime +7 -print 找出七天内未被更动的档案
26.cut命令
分割文件每一行选择的字段。
cut -c list [ file ... ]
cut -f list [ -d delim ] [ -s ] [ file ... ]
选项
-c list 此选项(无空格)确定字符位置list是以逗号分割的字段号码,说明域号的整数表(递增次序),可以用-表示范围,(c表示char):
-c 1,4,7 字符1,4和7
-c 1-8,9 字符1到3和8
-c -5,10 字符1到5和10
-c 3- 字符3到最后
-f list 此选项确定字段列表,以定界符分隔。没有字段定界符的行将完整传送,(f表示field)
-f 1,7 只拷贝第1和第7个字段。
-f 1-3 只拷贝第1到第3个字段。
-dchar 紧跟-d的字符char是字段定界符,缺省值为tab,对shell有特殊意义的字符必须用引号引起来。
-d” “ 使用一个空格作为定界符。(d表示define)
例子:
获取当前注册名
who am i | cut -f1 -d" "
将用户标识符映射成名称
cut -d: -f1,5 /etc/passwd
显示12 34
echo "12 34 567 89 0" | cut -d" " -f 1-2
显示12345
echo “12345678” | cut –c 1-5
诊断:
I “ERROR: line too long”
一行不能超过1023个字符或字段。
27.paste命令
合并几个文件中的相同行或同一文件其后的相同行。
paste [ -s ] [ -d list ] file ...
paste将file1 和file2 等的对应行连接起来,将每个文件看成是列或表的各列而将他们水平的粘贴在一起(平行合并)。
选项:
-d 无此选项时,文件中的每个换行符都由tab字符取代,但最后一个文件须除外(或在-s选项时最后一行除外)。此选项允许由list中一个或多个备用字符来替换tab字符(见下)。
list 代替tab成为行连接字符的一个或几个字符。即-d后面的list中的字符将依次作为行连接字符的一个或几个字符。如果是两个或多个文件合并,则作为每个文件行之间的连接字符。如果是一个文件自身合并,则作为每行的连接字符。List可包括:/n(新行)、/t(tab)、//(反斜杠)、/0(空行),但不能为null字符。
-s 合并后续行而不是各文件中的行。用tab作为连接符。
- 可代替文件名,以从标准行中读入一行(不给出提示)。
例子:
文件1.txt内容如下
1 2 3 4 5 6
a b c d e f
文件2.txt内容如下
11 22 33 44 55 66
aa bb cc dd ee ff
连接1.txt和2.txt的各行,以tab作为行连接字符
paste 1.txt 2.txt
输出:
1 2 3 4 5 6 11 22 33 44 55 66
a b c d e f aa bb cc dd ee ff
连接1.txt各行,以空格作为连接字符
1 2 3 4 5 6 a b c d e f
在一列中列出目录
ls | paste –
在四列中列出目录
ls | paste - - - -
将成对行合并成行
paste -d “/t/n” –s 1.txt
诊断:
“line too long:”
输出字符限制在511个
“too many files:”
除非用-s选择,否则最多只能指定12个输入文件。
28.rm命令
rm [-f][-i] file
rm [-r[-f][-i] dirname …[file…]
rmdir [-p][-s] dirname
rm删除一个目录中的一个或多个文件。
选项
-f 此选项删除所有的在目录中的文件(不管是否有无写保护),而不对用户进行提示。在有写保护的目录中不能对文件进行删除,但不显示任何信息。
-r 此选项删除参数中列出的所有目录和子目录。
例子:
删除目录mend_check_dir并且不回显
rm -fr $INSTALL_PATH/mend_check_dir >/dev/null 2>&1
29.mkdir命令
mkdir在方式777下建立目录(方式可用umask更改).
Mkdir [-mmode][-] dirname ...
选项:
-m 此选项允许用户指定新目录使用的方式.
-p 使用此选项,可以建立一个名为dirname且在父辈目录中不存在的目录。
例如:
建立目录dir1/dir2,即使dir1在当前目录中不存在。
mkdir -p dir1/dir2
30.cat命令
连接和显示文件。
cat [-u][-s][-v][-t][-e] file ...
cat按顺序读每个file,且将它写到标准输出上。
如果未给出文件名,或者遇到变元,cat将从标准输入文件上读。
例如:
打印file到终端
cat file
连接file1和file2,且把结果写入到file3
cat file1 file2 > file3
31.pkgadd命令
将软件包传送给系统。
pkgadd [-d device] [-r response][-n][-a admin][pkginst1 [pkginst2[…]]]
pkgadd将软件包的内容从安装它的分布介质或目录转送到系统。若没有使用-d选项,pkgadd在缺省的假脱机目录中查找该报(/var/spool/pkg)。若使用-s选项,就将该包读到假脱机目录而不安装它。
选项:
-d 从device安装或拷贝一个包。device可以是到目录的完整路径名。
pkginst 说明被安装的包实例或实例列表记号all可用来查阅在源介质上的所有可用包。
32.groupadd和mkgroup命令
把新的小组定义添加(建立)给系统
groupadd [-g gid[-0]] groupname
选项:
-g gid 对新组的组id。此组id必须是非负的十进制整数,此整数小于在<param.h>主文件中定义的MAXUID。
例如:
groupadd -g $GroupID $GroupName
注:HP和SUN平台使用“groupadd”命令。IBM平台使用“mkgroup”命令。
增加用户的命令见“五.54 useradd和mkuser命令”
33.ln命令
建立硬链或符号链。
ln [-fs] filename [linkname]
把filename连接到linkname。其中filename可以是一个或多个文件名,用户可建立多个file连接到linkname。
选项:
-s ln将建立一个象征性连接。
34.su命令
成为特殊用户或其他用户。
su [-][name[arg ......]]
su允许一个用户在未注销时成为另一个用户。
选项:
- 完成一个完全的注册。删除除TERM之外的环境中的所有变量,将USER设置为name,HOME和SHELL从被替换用户的口令文件中获得,将PATH设置为:/usr/ucb:/bin:/usr/bin,将目录更改为name的本地目录,并告诉shell读name的.login或.profile文件。
-f 完成一个快速的su。如果与C shell一起使用,将阻止C shell去读name的.cshrc文件,如果与Bourne shell一起使用,将不支持文件名生成。
例如:
执行ln命令和成为sms用户:
su - sms -c "ln -s $SCP_HOME/sms v20"
35.setenv命令
设置环境变量
例子:
设置环境变量INFORMIXDIR的值为$INFORMIX_HOME
setenv INFORMIXDIR "$INFORMIX_HOME"
36.repeat命令
用来执行只有一个固定次数的命令。
例子:
在屏幕上显示连字符(-)80次
repeat 80 echo ‘-‘
37.getopts命令
用来解析命令选项。
用法:
getopts optstring name[arg...]
说明:
optstring必须包含使用getopts将识别的选项字母,如果字母右跟随一个冒号,则选项期望有一个变元或变元组,并由空格分开。
每一次调用时,getopts把下一个选项放入shell变量Name中,且在shell变量OPTIND中处理下一个变元的索引;无论是调用shell和sehll过程,OPTIND初始化为1。
当一个选项需要一个选项变元,getopts把它放置在shell变量OPTARG中。
如果遇到一个非法选项,将把?放入name中。
当遇到选项结束时,getopts将带着一个非0出口状态退出;专用选项—-可以用来确定选项结束的边界。
在缺省状态下,getopts解析位置参数,如果getopts命令行中给出变元(arg...)则getopts将解析它们。
实例:
下述的shell程序框架显示如何处理选项a或b及选项o的命令变元的:
while getopts abo:c OPTION
do
case $OPTION in
a|b)
FLAG=$OPTION
;;
o)
ORAG=$OPTARG
;;
/?)
echo $USAGE
exit 2
;;
esac
done
shift `expr $OPTIND – 1`
此代码接收下述任意等价命令:
cmd –a –b -o123 file
cmd –a –b -- –o123 file #将忽略”—-“以后的选项
cmd –ab –o”xxx” file
cmd –o”xxx” –a –b file
38.sort命令
把所有命名文件一起排序和合并,并把结果写到标准输出上。如果使用’-‘作为文件名或者没有命名输入文件,则读标准输入。
简单用法:
sort [-dfiMnr][files]
下列选项重写缺省的排序规则:
-d ”Dictionary”排序,在比较时只人士字母、数位和空格
-f 将下档字符转化成上档字符
-i 忽略不可打印的字符
38.kill命令和trap命令
操作系统可以向脚本或命令发出消息,告知它们某个事件的发生,这些事件通常是内存错误、访问权限问题或某个用户试图停止你的进程等等。这些事件称之为信号。它们中的一些可以被shell脚本捕获。
如信号2就表示来自键盘的中断信号,当按下CTRL-C时触发此信号。信号2的名字是SIGINT, 2是信号的号码。
注:如果想查看所有信号,可以使用kill -l命令列出所有信号。
发送信号可以使用如下格式:
kill [-signal no: | signal name ] process ID
在脚本捕获信号的命令的形式如下:
trap command signal(s)
command是捕获到信号后用来处理的函数,需要使用引号扩起。
例如:
trap "" 2 3 忽略信号2和3
trap "commands" 2 3 如果捕捉到信号2或2,则执行相应的commands命令
下面是一个脚本例子,用trap 捕获signal 2:
#!/bin/sh
# use trap to catch signal 2 (CTRL-C)
# set trap
trap "catch_signal_two" 2
LOOP=0
# catch signal 2
catch_signal_two()
{
echo "You just hit <CTRL-C>, at number $LOOP"
echo "I will now exit"
exit 1
}
# loop
echo "Loop start, you can use CTRL-C to end."
while :
do
LOOP=`expr $LOOP + 1 `
echo $LOOP
done
注:当在catch_signal_two函数中不使用exit命令时,在while循环中触发以及处理完trap后,while循环还会从打断的地方继续执行。
39.操作系统和数据库检查(IBM)(一):检查核心参数的配置
#ulimit -a
time(seconds) unlimited
file(blocks) 2097151
data(kbytes) 262144
stack(kbytes) 32768
memory(kbytes) 32768
coredump(blocks) 2097151
nofiles(descriptors) 2000
40.操作系统和数据库检查(IBM)(二):检查时区的配置
#grep TZ /etc/environment
正确的格式为:TZ=BeiJing-8
说明:
TZ的格式: STDoffset[DST[offset][,rule]]
STD表示时区,DST表示夏令时;
当地时间加上offset就是UTC时间。rule为夏令时的规则.
41.操作系统和数据库检查(IBM)(三):检查硬件错误
#errpt –d H
如果有输出,则表示有硬件错误。
42.操作系统和数据库检查(IBM)(四):检查硬盘错误
#smitty ssaraid
选择第一项
如果第4列为good,则表示磁盘系统正常。
43.操作系统和数据库检查(IBM)(五):检查交换区的使用情况
#lsps –a
使用率不要超过70%,否则最好重起一把机器
44.操作系统和数据库检查(IBM)(六):检查内存的使用情况
#vmstat 2 50
r b avm fre re pi po fr sr cy in sy cs us sy id wa
0 1 167253 503710 0 0 0 0 0 0 908 2000 519 1 0 98 0
0 1 167253 503710 0 0 0 0 0 0 912 2001 524 2 0 98 0
如果fr或sr不为0,表示有内存申请操作;pi或po不为0,表示有page操作
45.操作系统和数据库检查(IBM)(七):检查系统的运行情况
#topas
可以看到CPU的使用情况,网卡的使用情况,磁盘的使用情况,进程的状态,内存的情况,交换区的情况等。
46.操作系统和数据库检查(IBM)(八):检查文件系统的使用情况
#df –k
Filesystem 1024-blocks Free %Used Iused %Iused Mounted on
/dev/hd4 32768 22516 32% 1421 9% /
/dev/hd2 2555904 1310716 49% 39736 7% /usr
/dev/hd9var 32768 12908 61% 263 4% /var
/dev/hd3 32768 2616 93% 293 4% /tmp
说明: %Used不能超过70%
%Iused不能超过90%
/tellinshare不能少于1G
/tellin的Free不能少于500M
47.操作系统和数据库检查(IBM)(九):检查文件系统的属性
#mount
node mounted vfs date options
------- ---------- ---- -------- ---------------
/dev/hd4 / jfs Jan 07 15:27 rw,log=/dev/hd8
/dev/hd2 /usr jfs Jan 07 15:27 rw,log=/dev/hd8
/dev/hd9var /var jfs Jan 07 15:27 rw,log=/dev/hd8
/dev/hd3 /tmp jfs Jan 07 15:27 rw,log=/dev/hd8
/dev/tellinlv /tellin jfs Jan 07 15:28 rw,log=/dev/hd8
说明:/tellinshare的options属性为rw,mind
48.操作系统和数据库检查(IBM)(十):HACMP检查
# /usr/sbin/cluster/clstat
clstat - HACMP Cluster Status Monitor
---------------------------------------------
Cluster: scu_cluster (177) Wed Jan 8 10:27:15 TAIST 2003
State: UP Nodes: 2
SubState: STABLE
Node: win1 State: UP
Interface: win1_boot (0) Address: 10.163.144.11
State: UP
Interface: win1_tty (1) Address: 0.0.0.0
State: UP
Node: win2 State: UP
Interface: win2_boot (0) Address: 10.163.144.13
State: UP
Interface: win2_tty (1) Address: 0.0.0.0
State: UP
49.操作系统和数据库检查(IBM)(十一):检查数据库的DR状态
对于主机
$ onstat –g ath|grep dr
57 d5bb53d8 d5a2f63c 2 cond wait drcb_bqf 1cpu dr_prsend
67 d5cbd670 d5a2fb28 2 sleeping secs: 1 1cpu dr_prping
68 d5cbda30 d5a30014 2 sleeping secs: 1 1cpu dr_btsend
对备机
$ onstat –g ath|grep dr
31 d5462030 d52dada0 3 cond wait netnorm 1cpu dr_secrcv
32 d5462678 d52db28c 3 cond wait drcb_bqf 1cpu dr_secapply
33 d5462a38 d52db778 3 sleeping secs: 6 1cpu dr_secping
34 d5462df8 d52dbc64 3 sleeping forever 1cpu dr_btrecv
50.操作系统和数据库检查(IBM)(十二):检查数据库的运行状态
$ onstat –p
Profile
dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits %cached
1653 5839 78992 97.91 31555 503390 1007 0.00
isamtot open start read write rewrite delete commit rollbk
112315 9475 17818 22031 0 0 0 0 0
gp_read gp_write gp_rewrt gp_del gp_alloc gp_free gp_curs
0 0 0 0 0 0 0
ovlock ovuserthread ovbuff usercpu syscpu numckpts flushes
0 0 0 17.51 23.79 5 11
bufwaits lokwaits lockreqs deadlks dltouts ckpwaits compress seqscans
855 0 0 0 0 0 10 208
ixda-RA idx-RA da-RA RA-pgsused lchwaits
0 2 1016 1018 69
说明:红色部分的数据为0就表示正常,否则需要调整运行参数
$ onstat –g sql
Sess SQL Current Iso Lock SQL ISAM F.E.
Id Stmt type Database Lvl Mode ERR ERR Vers
31 - vpn83200 CR Wait 5 0 0 7.24
30 - vpn83200 CR Wait 5 0 0 7.24
29 - vpn83200 CR Wait 5 0 0 7.24
28 - vpn83200 CR Wait 5 0 0 7.24
27 - vpn83200 CR Wait 5 0 0 7.24
26 - vpn83200 CR Wait 5 0 0 7.24
25 - vpn83200 CR Wait 5 0 0 7.24
24 - vpn83200 CR Wait 5 0 0 7.24
23 - vpn83200 CR Wait 5 0 0 7.24
21 - vpn83200 CR Wait 5 0 0 7.24
说明:关注是否出现ERR.
51.操作系统和数据库检查(IBM)(十三):数据库检查
$ oncheck –cc
Validating database vpn83200
Validating systables for database vpn83200
Validating syscolumns for database vpn83200
Validating sysindexes for database vpn83200
$ oncheck –cR
Validating Informix Dynamic Server reserved pages
Validating PAGE_PZERO...
Validating PAGE_CONFIG...
Validating PAGE_1CKPT & PAGE_2CKPT...
Using check point page PAGE_2CKPT.
Validating physical log pages ...
Validating logical logs ...
Validating PAGE_1DBSP & PAGE_2DBSP...
Using DBspace page PAGE_2DBSP.
Validating PAGE_1PCHUNK & PAGE_2PCHUNK...
Using primary chunk page PAGE_2PCHUNK.
Validating PAGE_1ARCH & PAGE_2ARCH...
Using archive page PAGE_2ARCH.
$ oncheck –cI iinscp
Validating indexes for vpn83200:vpn83200.lactovlr...
Index 212_494
Validating indexes for vpn83200:vpn83200.mvpn_phone...
Index 213_498
Index mvpn_phone_index2
Index mvpn_phone_index1
52.操作系统和数据库检查(IBM)(十四):检查数据库的运行日志
$ vi online.log
主要看Checkpoint的时间和频度,是否有断言错误等
53.fsck命令
检查和修复文件系统。
例如:
fsck –y #不需要确认直接检查和修复文件系统。
54.useradd和mkuser命令
为组添加用户。
useradd -d <HOME目录> -g <所属组> -s /usr/bin/csh -m <用户名>
例如:
如在SUN下创建smpsys用户:
useradd -d /home/smpsys -g sms -s /bin/csh -m smpsys
注:
HP和SUN平台用useradd命令,IBM平台使用“mkuser”命令,命令格式为:
mkuser pgrp=<所属组> home=<HOME目录> shell=/usr/bin/csh <用户名>
54.exec命令
1.执行命令和程序来取代当前进程
exec command
当执行完毕后,不能返回调用进程,回返回到调用进程的父进程。
2.打开和关闭文件描述符
用于文件输入输出的exec命令的语法
exec < file 打开’file’以进行读操作,并把进程的标准输入链接到’file’
exec > file 打开’file’以进行写操作,并把进程的标准输出链接到’file’
exec >> file 打开’file’以进行写操作,把进程的标准输出链接到’file’,并把标准输出添加到 ‘file’
exec n<file 打开’file’以进行读操作,并给它分配文件描述符’n’
exec n>file 打开’file’以进行写操作,并给它分配文件描述府’n’
exec n<<tat…tag 打开一个here文档(位于<<’tag’和’tag’之间的数据)以进行读操作,并给它分配文件描述符’n’
exec n>>file 打开’file’以进行写操作,给它分配文件描述符’n’,并把数据添加到’file’尾部
exec n>&m 把’m’复制到’n’;任何到文件描述符为’n’的文件的数据也会被发送到文件描述符为’m’的文件
exec <&- 关闭标准输入
exec >&- 关闭标准输出
exec n<&- 关闭链接到标准输入的描述符为’n’的’file’
exec n>&- 关闭链接到标准输出的描述符为’n’的’file’
当在命令行执行exec < sample 命令时,它把当前的shell的标准输入链接到sample文件.当在一个脚本里执行时,该命令把脚本的标准输如重定向到sample文件. 如果要恢复,需要执行exec </dev/tty命令把标准输入重新链接到终端.
54.tr命令
小写到大写
echo $var | tr “[a-z]” “[A-Z]”
echo $var | tr “[:lower:]” “[:upper:]”
大写到小写
echo $var | tr “[A-Z]” “[a-z]”
echo $var | tr “[:upper:]” “[:lower:]”
1.setenv PATH和set path = (....)
解答:
set path仅仅作用于当前的shell,setenv也对子shell起作用。
csh中使用setenv来设置环境变量。
ksh中使用export来设置环境变量。
csh:
setenv ENV_NAME ENV_VALUE
ksh
export ENV_NAME=ENV_VALUE
也可以分步:
ENV_NAME=ENV_VALUE
export ENV_NAME
2.awk中输出单引号
echo "a b c" |awk '{print $1 单引号 $2 单引号 $3}'
我要给b加单引号,输出成下面格式:
a 'b' c
解答:
echo "a b c"|awk '{printf("%s %c%s%c %s/n",$1,39,$2,39,$3)}'
3.awk或read找出文件行字符数大于80的行
方法一:使用awk的NR
awk '
{
line_len=length
if (line_len >80)
print NR":"line_len
}' <$1
注:若length函数不加参数,则表示处理当前行
方法二:使用read,循环处理
while read line
do
count=`echo $line|wc -C`
countnum=`expr $count - 1`
if [ $countnum -gt 80 ]; then
echo "$linecount: ($countnum) $line"
fi
done < $1
4.shell脚本程序中的用户切换:
切换到另一个用户,执行几个操作然后退出来,整个过程不退出脚本执行
解答:
su -bin -c command arguments
5.shell中删除文件且不显示输出信息和出错信息
解答;
rm ${HOME}/bin/.filesize > /dev/null 2>&1
>为重定向符号,2>&1表示标准错误输出定向导标准输出,又由于标准输出被定向到/dev/null,所以两者都被定向导/dev/null。
6.shell变量赋初值时存在特殊字符
以下程序无法正常运行:
name=”test”
pwd=”$google”
ftp -in $1 <<FTP_CMD
user $name $pwd
ls
bye
FTP_CMD
原因是$是特殊字符。解决方法,使用单引号’
pwd=’$google’
建议:字符串赋初值均采用单引号’
7.sed的参数串中存在/特殊字符
需要把 /export/home/mywork 转换为 //export//home//mywork
先构造转化如下:
echo "/export/home/mywork" | sed "s/g"
在bsh和ksh下不能运行,在csh下可正常运行。
原因是对sed的表达式的解析不能完成。解决方法,使用单引号’
echo "/export/home/mywork" | sed 's/g'
建议:对sed的表达式均采用单引号’
8.find在一个目录下找包含一个字符串的所有文件
find ./ -name "*.sh" | xargs grep "set"
find . -name "*.sh" -exec grep -l "set" {} /;
9.shell中确定一个文件的存在,文件ins_billdb
if [ ! -f $INSTALL_PATH/ins_billdb ]; then
10.read的参数与实际域的个数不同
read只读取一行的文本,当read的参数多于实际域个数时,多余的参数为空,不会读取到下一行;当read的参数少于实际域个数时,最后一个参数的值包含剩下所有域。
例如:
文件内容:1 2
使用 read arg1 arg2 arg3读取时,arg3为空。
使用 read arg1读取时, arg1为1 2
11.grep获取主机名和IP地址
方法一.从host文件获取
##############################################
# name : get_host_info
# description: get host name and ip address
# input: N/A
# output: HostName , HostIP
# return: 0 –- get successfuly
# others -- get failure
##############################################
get_host_info()
{
HostName=`hostname`
#过滤纯注释行(以#开头或者以 空格+#开头的行),
#然后过滤127.0.0.1,获取本机的ip地址
HostIP=`cat /etc/hosts|grep -v "^[ ]*/#" | grep -v 127.0.0.1 | grep $HostName | awk '{print $1}'`
if [ $? -ne 0 ];then
echo "Error! can't get Host IP"
return 1
fi
if [ $? –eq 0 ]; then
return 0;
else
return 1;
fi
}
方法二.从ifconfig获取
##############################################
# name : get_host_info
# description: get host name and ip address
# input: N/A
# output: HostName , HostIP
# return: 0 –- get successfuly
# others -- get failure
##############################################
get_host_info()
{
#得到ip地址所在行
ip=`ifconfig -a | grep [1-9][0-9]/{0,2/}/.[0-9]/{1,3/}/.[0-9]/{1,3/}/.[0-9]/{1,3/}" | awk '{print $2}'`
#提取ip地址
ip=`echo $ip | awk '{print $2}'`
is_ip_address $ip
if [ $? –eq 0 ]; then
return 0;
else
return 1;
fi
}
注:is_ip_address函数见“六.13 确定字符串是否是ip地址”
12.grep确定变量不是数字
见“31.iTELLIN示例十五:判断一个字符串是否是整数”
13.确定字符串是否是ip地址
##############################################
# name : is_ip_address
# description: judge whether the string
# is a ip address
# input: string
# return: 0 –- is ip address
# others -- not ip address
##############################################
is_ip_address()
{
TmpValue=$1
nCount=`echo "$TmpValue" |grep –c [1-9][0-9]/{0,2/}/.[0-9]/{1,3/}/.[0-9]/{1,3/}/.[0-9]/{1,3/}'`
if [ 1 –eq $nCount ]; then
# remove the char ‘.’ from $TmpValue
TmpValue="`echo $TmpValue | sed 's//./ /' | sed 's//./ /' | sed 's//./ /'`"
for i in $TmpValue
do
if [ "$i" -gt 255 ]; then
#echo "Error! $TmpValue is not a IP address!"
return 1
fi
done
return 0
else
#echo "Error! $TmpName is not a IP address!"
return 1
fi
}
14.grep列出某个用户的所有进程:
USER_NAME
ps -ef | grep "^[ ]*$USER_ NAME"
grep查找以0到多个空格和用户名开头的行。
15.grep和awk列出某个目录下的一级子目录
DIR=$1
ls -l $DIR | grep '^[ ]*d/.*' | awk '{print $9}'
ls –l列表的第九项为文件名。如果不加入awk的过滤,则打印子文件夹详细信息。
16.用printf将一个数打印成逗号分隔的形式
以下为awk中的程序。
函数名: int_add_comma
功能 : 将传入的整数转化为每N位加一个逗号形式的字符串。
参数 :
num : 需要被转化的整数
ret : 存贮转化以后的字符串,空间由调用者提供
N : 间隔位数
返回值:
0 --转换正常,结果存放在ret中。
-1 --转换失败,传入参数不符合要求。
例子:
调用:
char buf[10] = "";
nret = int_add_comma(1234,buf,3);
返回:
nret=1
buf="1,234"
*/
int int_add_comma(long num,char *ret, int N)
{
char buf[10] = "";
char *p, *q;
int i, j, ncount, nleft;
if (ret == NULL || N <= 0 )
return -1;
sprintf(buf, "%u", num);
ncount = strlen(buf) / N;
nleft = strlen(buf) % N;
for (p=buf,q=ret,i=0; i<nleft; i++)
*q++ = *p++;
if (nleft > 0)
*q++ = ',';
for (i=0; i<ncount; i++)
{
for (j=0; j<N; j++)
*q++ = *p++;
if (i < ncount-1)
*q++ = ',';
}
*q = '/0';
return 0;
}
17.iTELLIN示例一:在ksh中使用数组
a) 初始化数组函数:
#!/usr/bin/ksh
sub_init_var()
{
HOST_NAME[0]="" #Save var name array
HOST_VALUE[0]="" #Save var value array
HOST_COMMENTS[0]="" #Save var commentS array
HOST_TYPE[0]="" #Save var type array
HOST_COUNT=0 #Save array element Count
}
注:其中HOST_NAME等为数组,HOST_COUNT为全局的HOST个数,虽然是在sub_init_var中声明,但是变量作用域是全局的。
b) 循环给数组赋值,取数组元素个数,访问数组元素、数组元素长度
#!/bin/ksh
datalist=`ls -l | awk '{print $9}'`
index=0
for j in $datalist
do
datalist[$index]=$j
let index+=1 #或者 index=`expr $index + 1`
done
index=0
# ${#datalist[@]}数组元素个数
while [ $index -lt ${#datalist[@]} ]
do
# ${datalist[index]}数组元素
# ${#datalist[index]}数组元素长度
echo “${datalist[index]} length is ${#datalist[index]}
let index+=1 #或者 index=`expr $index + 1`
done
18.iTELLIN示例二:从文件中读取参数:
文件存放格式:
[HOST]
g_Node1_Host itellin1 #Node 1 host name
g_Node2_Host itellin2 #Node 2 host name
g_ClusterName itellin #Cluster name
[DEVICE]
SMC_IP 10.76.137.101 #Service Manager Center IP
SMC_LISTEN_PORT 5060 #Service Manager Center Listen portal
Set_FireWall NO #Portal FireWall Set
FireWallIP 10.76.137.156 #Portal FireWallLogic host IP
... ...
文件读取函数:
###########################################################
# 函数:read_var
# 目的:从全局配置文件中读取变量值
# 方法:
# 输入:全局配置文件名
# 输出:全局配置文件中的变量值
# 限制:
###########################################################
read_var()
{
#参数个数是否是一个
if [ $# -ne 1 ]; then
echo "Error usage!"
exit 1
fi
CfgFile=$1
#参数所代表的配置文件是否存在
if [ ! -f $CfgFile ]; then
sub_echo_log "File $CfgFile does not exist!"
exit 1
fi
echo "/nread configuring file, wait..."
#读取 NAME VALUE COMMENT
while read VarName VarValue VarTemp
do
#如果是读取 HOST 段的信息
if [ "1" -eq "`echo "$VarName" | grep -c '/[HOST/]'`" ]; then
while read VarName VarValue VarTemp
do
if [ "-$VarName" = "-" ]; then
continue
#如果是 [xxxx]形式的文本
elif [ "1" -eq "`echo "$VarName" | grep -c '/[.*/]'`" ]; then
break
else
HOST_NAME[HOST_COUNT]="$VarName"
#如果是注释(以#开头)
if [ "1" -eq "`echo "$VarValue" | grep -c '^#.*'`" ]; then
HOST_VALUE[HOST_COUNT]=""
HOST_COMME[HOST_COUNT]=""
else
HOST_VALUE[HOST_COUNT]="$VarValue"
HOST_COMME [HOST_COUNT]="$VarTemp"
fi
((HOST_COUNT=HOST_COUNT+1))
fi
done
fi
#如果是读取 DEIVCE 段的信息
#格式同HOST段的读取
... ...
continue
done < $CfgFile
sub_echo_log "read configuring file $SrcFile ok"
}
19.iTELLIN示例三:包含其它脚本文件
使用操作符.包含另一个脚本文件package.cfg:
. $INSTALL_PATH/package.cfg
其中package.cfg文件内容如下:
#压缩文件名
SCP_CMPD_FILE="iSCP_INSTALL.tar.Z"
SMP_CMPD_FILE="iSMP_INSTALL.tar.Z"
MML_CMPD_FILE="MMLSERVER_install.tar.Z"
WMAS_CMPD_FILE1="WmasBin.tar.Z"
WMAS_CMPD_FILE2="WmasRunEnv.tar.Z"
... ...
20.iTELLIN示例四:初始化一个临时文件供使用
##############################################
# name : sub_initfile
# description: initialize a temp file for use
# input: temp file name
# return: N/A
##############################################
sub_initfile()
{
FileName="$*"
if [ -f $FileName ]; then
rm -f $FileName
fi
touch $FileName
chmod 666 $FileName
}
初始化一个临时文件,将df输出结果写入临时文件,显示临时文件内容
sub_initfile $TmpFile
df -k > $TmpFile
if [ "$?" != "0" ]; then
sub_echo_log "Error! Check file system failure!"
exit 1
fi
echo "/n*************** file system BEGIN ***************/n"
cat "$TmpFile"
echo "/n** ************* file system END ***************/n"
21.iTELLIN示例五:分解字符串
字符串为"set shmsys:shminfo_shmmax=256000000",为函数参数
分解代码如下:
system_set_value()
{
TmpInf=$*
#得到TmpInf1="256000000"
TmpInf1="`echo $TmpInf | awk -F= '{print $2}' | awk '{print $1}'`"
#得到TmpInf="set shmsys:shminfo_shmmax"
TmpInf="`echo $TmpInf | awk -F= '{print $1}'`"
#得到TmpInf2="shminfo_shmmax"
TmpInf2="`echo $TmpInf | awk -F: '{print $2}' | awk '{print $1}'`"
#得到TmpInf="set shmsys"
TmpInf="`echo $TmpInf | awk -F: '{print $1}'`"
#得到TmpInf3=" shmsys"
TmpInf3="`echo $TmpInf | awk '{print $2}'`"
#得到TmpInf4="set"
TmpInf4="`echo $TmpInf | awk '{print $1}'`"
}
22.iTELLIN示例六:替换配置文件中的值
配置文件中的配置参数被设置参数取代。
如配置文件为$TmpFile,里面有一行为
set shmsys:shminfo_shmmax=256000000
shell代码中的缺省配置为
set shmsys:shminfo_shmmax=199000000
在得到用户许可以后,使用缺省配置代替$TmpFile中的值,代码如下:
#从缺省配置行得到变量TmpInf1,TmpInf2,TmpInf3,TmpInf4(见上例)
SetInf="set shmsys:shminfo_shmmax=256000000"
system_set_value $SetInf
#得到配置文件的拷贝
cat "/etc/system" > $TmpFile
#如果配置文件中有相应的配置行
if [ "1" -eq `cat $TmpFile | grep -v "^[ ]*/*" | grep $TmpInf4 | grep $TmpInf3 | grep -c $TmpInf2` ]; then
#得到配置文件的配置行
MyInf=`cat $TmpFile | grep -v "^[ ]*/*" | grep $TmpInf4 | grep $TmpInf3 | grep $TmpInf2`
#保存缺省配置的数值
OldTmpInf1="$TmpInf1"
#从文件配置行得到变量TmpInf1,TmpInf2,TmpInf3,TmpInf4
system_set_value $MyInf
#若文件配置行中的数值和缺省配置行的数值不同
if [ "$OldTmpInf1" != "$TmpInf1" ]; then
echo "Warning! Your value is $TmpInf1, but default value is $OldTmpInf1."
sub_echo_read "Are you want to replace it? (y/n):/c"
if [ "$SurCho" = "n" ]; then
sub_echo_log "Warning! $MyInf was not default value."
else
#使用缺省配置行替换配置文件中的配置行,并写回到配置文件中
cat $TmpFile | sed "s/$MyInf/$SetInf/" > $TmpFile1
cp $TmpFile1 $TmpFile
sub_echo_log "OK! $TmpInf1 was replaced with $OldTmpInf1"
fi
fi
else #若配置文件中不存在相应的配置行
sub_echo_log "Error! not $SetInf"
#将缺省配置行添加到配置文件中
echo "$SetInf" >> $TmpFile
sub_echo_log "OK! Add $SetInf"
fi
23.iTELLIN示例七:取得字符串的长度 ##############################################
# name : get_length
# description: get the length of string
# input: string
# return: lenght of string
##############################################
get_length()
{
return `echo $1 | awk '{print length($0)}'`
}
取得字符串$0的长度,用以判断其最后一个字符是否是字符/,如果是,则删除此字符
get_length $FileDir
StrLength=$?
if [ "/" = "`echo $FileDir | cut –c $StrLength`" ]; then
((StrLength=StrLength-1)) #此行sh不支持,应改用expr
FileDir="`echo $FileDir | cut -c1-$StrLength`"
fi
24.iTELLIN示例八:用另外的文件作为函数库
主程序在autoinstall文件中执行,有一个解压缩的功能由另一个文件file_uncmp实现,则在autoinstall文件中调用如下:
#调用file_uncmp文件中的函数解压缩
$IN_PATH/file_uncmp $CmpdFile $IN_PATH/mend_check_dir
在file_uncmp文件中:
#!/bin/ksh
file_uncmp()
{
......
}
if [ $# -ne 2 ]; then
echo "Error usage!"
exit 1
fi
file_uncmp $1 $2
25.iTELLIN示例九:解压缩文件到一个目录
###########################################################
# 函数:file_uncmp
# 目的:压缩文件解压
# 方法:
# 输入:压缩文件名,解压路径
# 输出:解压后的目录和文件
# 限制:
###########################################################
file_uncmp()
{
#$1为压缩文件的全路径
CmpdFile=$1
#$2为目录
UncmpPath=$2
#判断解压路径是否正确
CurDir="`pwd`"
if [ "$UncmpPath" != "$CurDir" ]; then
echo "Error uncompress path $UncmpPath!"
exit 1
fi
#判断解压文件是否存在
if [ ! -f $CmpdFile ]; then
echo "File $CmpdFile not find."
exit 1
fi
#删除解压缩目的目录中的所有文件。
rm -f $UncmpPath/*.tar.Z
rm -f $UncmpPath/*.tar
rm -f $UncmpPath/*.CPI
rm -f $UncmpPath/*.war
echo "/nCopy file, Please wait......"
#将压缩文件拷贝到目录目录中(判断操作是否成功)
cp $CmpdFile $UncmpPath
if [ "$?" -ne 0 ]; then
echo "Can not access file $CmpdFile"
exit 1
fi
SrcfType=false
echo "/nUncompress file. Please wait......"
#判断是否存在tar.Z文件
ls *.tar.Z > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
SrcFile="`ls *.tar.Z`"
SrcfType=true
Opts="`uncompress -f $SrcFile`"
Rtns=$?
if [ $Rtns -ne 0 ]; then
echo "$Opts"
echo "Uncompress file $SrcFile failed!"
exit 1
fi
fi
#判断是否存在tar文件
ls *.TAR > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
SrcFile="`ls *.TAR`"
SrcfType=true
Opts="`tar xvf $SrcFile`"
Rtns=$?
if [ $Rtns -ne 0 ]; then
echo "$Opts"
echo "TAR file $SrcFile failed!"
exit 1
fi
rm -f $UncmpPath/*.TAR
exit 0
fi
ls *.tar > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
SrcFile="`ls *.tar`"
SrcfType=true
Opts="`tar xvf $SrcFile`"
Rtns=$?
if [ $Rtns -ne 0 ]; then
echo "$Opts"
echo "Tar file $SrcFile failed!"
exit 1
fi
fi
ls *.war > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
SrcFile="`ls *.war`"
SrcfType=true
Opts="`jar xvf $SrcFile`"
Rtns=$?
if [ $Rtns -ne 0 ]; then
echo "$Opts"
echo "Tar file $SrcFile failed!"
exit 1
fi
fi
ls *.CPI > /dev/null 2>&1
if [ "$?" -eq 0 ]; then
SrcFile="`ls *.CPI`"
SrcfType="TRUE"
Opts="`cpio -icvumd < $SrcFile`"
Rtns=$?
if [ $Rtns -ne 0 ]; then
echo "$Opts"
sub_echo_log "Cpio SCP source file $SrcFile failed!"
exit 1
fi
fi
if [ "$SrcfType" = false ]; then
echo "Format of source file $CmpdFile is not known!"
exit 1
fi
echo ""
echo "Uncompress file completed."
rm -f $UncmpPath/*.tar.Z
rm -f $UncmpPath/*.tar
rm -f $UncmpPath/*.CPI
}#end of file_uncmp()
26.iTELLIN示例十:判断操作是否成功
拷贝:
cp $CmpdFile $UncmpPath
if [ "$?" -ne 0 ]; then
echo "Can not access file $CmpdFile"
exit 1
fi
取得主机名和IP地址:
#获取主机名
HostName=`hostname`
#过滤纯注释行(以#开头或者以 空格+#开头的行),
#然后过滤127.0.0.1,获取本机的ip地址
HostIP=`cat /etc/hosts|grep -v "^[ ]*/#"|grep -v 127.0.0.1|grep $HostName|awk '{print $1}'`
if [ $? -ne 0 ];then
sub_echo_log "Error! can't get Host IP"
exit 1
fi
检测系统:
echo "Your SunOs version is `uname -r`"
if [ "$?" != "0" ]; then
sub_echo_log "Error! Check solaris version failure!"
return
fi
一些要判断操作结果是否成功的命令:
cp、cat、df、ls、pkginfo、ifconfig、ping、uname、mkdir、pkgadd、su、cd、netstat、groupadd、groupdel
27.iTELLIN示例十一:封装创建一个组的函数
以下函数创建一个组,调用:group_creat "informix" "101
###############################################################
# 函数:group_creat
# 目的:创建组
# 方法:
# 输入:组名、组ID
# 输出:组
# 限制:
###############################################################
group_create()
{
#如果存在此组或者存在和组ID相同的组,均删除,然后重新创建一个组
if [ ! -f "/etc/group" ]; then
echo "File /etc/group does not exist!"
exit 1
fi
#$1为组名,$2为组ID
GroupName=$1
GroupID=$2
GroupFlag=false
while read LineContent
do
OldGroupName="`echo "$LineContent" | awk -F: '{print $1}'`"
if [ "$GroupName" = "$OldGroupName" ]; then
GroupFlag=true
break
fi
done < "/etc/group"
if [ "$GroupFlag" = true ]; then
groupdel $OldGroupName
sub_echo_log "Del group $OldGroupName existed."
fi
GroupFlag=false
while read LineContent
do
OldGroupID="`echo "$LineContent" | awk -F: '{print $3}'`"
if [ "$GroupID" = "$OldGroupID" ]; then
OldGroupName="`echo "$LineContent" | awk -F: '{print $1}'`"
GroupFlag=true
break
fi
done < "/etc/group"
if [ "$GroupFlag" = true ]; then
exec_Cmd "groupdel $OldGroupName"
sub_echo_log "Del group $OldGroupName existed for the same group ID."
fi
exec_Cmd "groupadd -g $GroupID $GroupName"
sub_echo_log "OK! Creat group $GroupName."
}
28.iTELLIN示例十二:封装创建一个用户的函数
##################################################################
#函数:user_creat
# 目的:自动创建用户
# 方法:
# 输入:用户名,用户ID,组名,主目录
# 输出:用户
# 限制:
#################################################################
user_creat()
{
if [ ! -f "/etc/passwd" ]; then
echo "File /etc/passwd does not exist!"
exit 1
fi
UserName=$1
UserID=$2
GroupName=$3
HomePath=$4
UserFlag=false
while read LineContent
do
OldUserName="`echo "$LineContent" | awk -F: '{print $1}'`"
if [ "$UserName" = "$OldUserName" ]; then
UserFlag=true
break
fi
done < "/etc/passwd"
if [ "$UserFlag" = true ]; then
echo "Delete old files, wait......"
#删除主目录中的所有文件
rm -r $HomePath/* >> /dev/null 2>&1
#删除用户
userdel $OldUserName
sub_echo_log "Del user $OldUserName existed."
fi
UserFlag=false
while read LineContent
do
OldUserID="`echo "$LineContent" | awk -F: '{print $3}'`"
if [ "$UserID" = "$OldUserID" ]; then
OldUserName="`echo "$LineContent" | awk -F: '{print $1}'`"
UserFlag=true
break
fi
done < "/etc/passwd"
if [ "$UserFlag" = true ]; then
#删除主目录中的所有文件
su - $OldUserName -c "rm -r *; rm -r .*" >> /dev/null 2>&1
#删除用户
userdel $OldUserName
sub_echo_log "Del user $OldUserName existed for the same user ID."
fi
useradd -u $UserID -d $HomePath -g $GroupName -s /bin/csh -m -k /etc/skel $UserName
chgrp $GroupName $HomePath
chown $UserName $HomePath
#如果是sms用户则建到scp用户的链接
if [ "$UserName" = "sms" ]; then
rm $SMS_HOME/v20 > /dev/null 2>&1
su - sms -c "ln -s $SCP_HOME/sms v20"
if [ "$?" != "0" ]; then
sub_echo_log "Error! Creat sign link v20 failure."
fi
fi
sub_echo_log "OK! Creat user $UserName."
echo "Please input user $UserName password."
passwd $UserName
}
29.iTELLIN示例十三:判断一个字符串是否是正整数
##############################################
# name : is_positive_integer
# description: judge whether the string is a positive integer
# input: string
# output: 0--is positive integer
# others--not a positive integer
##############################################
is_positive_integer()
{
Str=$1
# trim the left and right space
Str=`echo $Str`
# is null string ?
if [ "-${Str}" = "-" ]; then
#echo "null str"
return 1
fi
# is equal zero
if [ "-${Str}" = "-0" ]; then
#echo "equal zero"
return 1
else
# try to remove number characters from the string
nRes=`echo ${Str} | sed 's/[0-9]*//g'`
# get the length of the remained string
nLen="`echo ${nRes} | awk '{print length($0)}'`"
# if has characters remained
if [ nLen -ne 0 ]; then
#echo "contain others characters or less than zero"
return 1
else
#echo "is positive integer"
return 0
fi
fi
}
30.iTELLIN示例十四:判断当前用户是否有root权限
#检查是否为root用户
Opts=`id | grep '(root)' | grep -c 'uid=0'`
if [ ${Opts} -eq 0 ]; then
echo "Error! autoinstall must run with root user."
exit 1
fi
31.iTELLIN示例十五:判断一个字符串是否是整数
##############################################
# name : is_integer
# description: judge whether the string is a integer
# input: string
# output: 0--is integer
# others--not a positive integer
##############################################
is_integer()
{
Str=$1
# trim the left and right space
Str=`echo $Str`
if [ "-$Str" = "-" ]; then
#echo "null str"
return 1
fi
# try to remove number characters from the string
nRes=`echo ${Str} | sed 's/^/([+-]*/)[0-9][0-9]*//g'`
# get the length of the remained string
nlen="`echo ${nRes} | awk '{print length($0)}'`"
# if has characters remained
if [ "-$nlen" != "-0" ]; then
# echo "contain others characters or less than zero"
return 1
else
#echo "is a integer"
return 0
fi
}
32.iTELLIN示例十六:删除某个文件夹下若干天以来未改动的文件
##############################################
# name : rm_file_ago
# description: rm files days ago
# input: directory
# ndays : days ago
# return: N/A
##############################################
rm_file_days_ago()
{
list=`find $1 -mtime +$2 -print`
for file in $list
do
echo "rm $file"
rm -fr $file
done
}
33.各种Unix环境对ksh的影响:
(1) IBM对$0的支持:
IBM机器不支持函数中使用$0代替函数名,它的$0总是代表sh文件的名字,所以不能使用$0来代表函数名.
(2) SUN对awk的支持:
awk的-v可以将shell中的变量传入到awk内部变量,但是SUN的awk不一定支持这个语法,如果要确保支持本语法,可以使用
/usr/xpg4/bin/awk -v key="$key_name" -v value="$svalue"
要注意两点:1.路径 2.-v和变量之间有空格(普通awk没有空格)
(3) SUN对grep的支持:
grep –E 的扩展支持在SUN下必须使用:
/usr/xpg4/bin/grep -E 'Archive| [0-9][0-9]:[0-9][0-9]:[0-9][0-9] '
(4) ~的使用
一般使用~iinscu即可得到iinscu的home目录.但是当把iinscu保存在变量中时,如 user_name=”iinscu”, 无法使用 ~$user_name得到iinscu的home路径.可以使用:
eval “home=~$user_name”
或者使用$user_name在/etc/passwd中查找:
home=`cat /etc/passwd | grep “^${user_name}:” | awk ‘{print $6 }’`
(5) su 某个用户并执行某个sh,输出到/dev/null中.
如 su – informix –c “ls -l >/dev/null 2>&1 “ >/dev/null 2>&1
在sh,csh下会出错,需要指定为ksh
su – infomix –c “ ksh =-c /” ls –l >/dev/null 2>&1 /” “>/dev/null 2>&1
在csh下可能会提示你 “不匹配, 需要将当前sh改成ksh.脚本中需要指定为ksh.
34.set 使用注意点:
set $str
当$str为空时,会打印出所有的变量,所以在执行操作前要检查$str是否为空.或者使用set “$str”也可
35.判断对端节点的文件是否存在:
count=`remsh infox_2 ls /tmp/abc 2>/dev/null | wc -l`
if [ $count -eq 0 ]; then
echo "not find"
else
echo "find"
fi
36.awk的split函数的使用:
#! /bin/awk
BEGIN {
record="abc#def#ghi";
split(record,myarray,"#");
}
END { for (i in myarray) {printf myarray[i]} };
$ awk -f aa.awk /dev/null
37.统计字符串在文件中出现的次数:
注意:在SUN下,其中的grep 要使用 /usr/xpg4/bin/grep, awk要使用 /usr/xpg4/bin/awk, 详细情况请参见本章33条.
################################################################# 函数名: count_str_in_file
# 目的:统计字符串在文件中出现的次数
# 方法:
# 输入:
# 1. file name : 要查找的文件的名字
# 2. key word : 要查找的关键字
# 3. match case : 是否区分大小写, 1 --区分 , 0 --不区分
# 4. math whole word only :是否整字匹配,1--整字匹配 ,0--不整字匹配
# 输出:
# g_total_num 变量存放统计的次数
# 返回值:
# 0 --成功 ,
# 1 --参数数目不正确
# 2 --文件不存在
# 3 --参数类型不合法
################################################################
count_str_in_file()
{
typeset func_name="count_str_in_file"
typeset file="$1"
typeset keyword="$2"
typeset match_case="$3"
typeset math_whole_word="$4"
typeset exp_str=""
typeset nums=""
typeset n=""
typeset total=""
typeset os_type=""
typeset new_grep=""
typeset new_awk=""
if [ $# -ne 4 ]; then
echo "parameters isn't 4"
return 1
fi
if [ ! -f "$file" ]; then
echo "can't find the file:$file"
return 2
fi
if [ "$match_case" != "1" -a "$match_case" != "0" ]; then
echo "match_case parameter invalidate:$match_case"
return 3
fi
if [ "$math_whole_word" != "1" -a "$math_whole_word" != "0" ]; then
echo "math_whole_word parameter invalidate:$math_whole_word"
return 3
fi
# 系统兼容
new_grep="grep"
new_awk="awk"
os_type=$(uname -s)
if [ "$os_type" = "SunOS" ]; then
new_grep="/usr/xpg4/bin/grep"
new_awk="/usr/xpg4/bin/awk"
fi
# 转义keyword中的特殊字符
# 特殊字符:$ . ' " * [ ] ^ | / + ?
# $
keyword=$(echo $keyword | sed 's//$///$/g')
# .
keyword=$(echo $keyword | sed 's//.///./g')
# "
keyword=$(echo $keyword | sed 's/"///"/g')
# *
keyword=$(echo $keyword | sed 's/*///*/g')
# [
keyword=$(echo $keyword | sed 's//[///[/g')
# ]
keyword=$(echo $keyword | sed 's//]///]/g')
# ^
keyword=$(echo $keyword | sed 's//^///^/g')
# |
keyword=$(echo $keyword | sed 's//|///|/g')
# /
keyword=$(echo $keyword | sed 's/g')
# +
keyword=$(echo $keyword | sed 's//+///+/g')
if [ "$match_case" = "1" ] ;then # 区分大小写
exe_cmd="tee"
if [ "$math_whole_word" = "1" ]; then # 整字匹配
exp_str="(^[ ]*$keyword[ ])|(^[ ]*$keyword[ ]*$)|([ ]$keyword[ ])|([ ]$keyword[ ]*$)"
else
exp_str="$keyword"
fi
else
exe_cmd="tr '[:upper:]' '[:lower:]' "
keyword="`echo $keyword | tr '[:upper:]' '[:lower:]'`"
if [ "$math_whole_word" = "1" ]; then # 整字匹配
exp_str="(^[ ]*$keyword[ ])|(^[ ]*$keyword[ ]*$)|([ ]$keyword[ ])|([ ]$keyword[ ]*$)"
else
exp_str="$keyword"
fi
fi
echo "debug keyword:$keyword"
echo "debug exp:--$exp_str--"
nums=$(cat $file | $exe_cmd | $new_grep -E "$exp_str" | $new_awk -v t="$keyword" '{
str=$0;
n=index($0,t);
keylen=length(t);
ncount=0;
while(n != 0)
{
ncount++;
str=substr(str,n+keylen);
n=index(str,t);
}
print ncount;
}')
total=0
for n in $nums
do
((total=total+n))
done
g_total_num=$total
}
# 查找非字母数字等字符时,使用非全字匹配
count_str_in_file inst_app.sh '/"' "0" "0"
echo "$g_total_num"
count_str_in_file "inst_app.sh" "/[" "1" "0"
echo "$g_total_num"
count_str_in_file "inst_app.sh" "if" "1" "1"
echo "$g_total_num"
count_str_in_file "inst_app.sh" "/*" "0" "0"
echo "$g_total_num"
38.如何进行精确匹配:
除了特殊平台使用特殊的选项外(如sun 平台对grep 使用 –w选项)
以下方法可以通用并且扩展:
精确匹配需要满足以下条件(暂不考虑由于标点符号分隔导致"hello world" 也要匹配到hello这种情况,如果要匹配这种情况,需要添加 前/后条件并同时修改 s_num和e_num):
keyword前: 开头+n个空白(n>=0): ^[ ]*
keyword前: 1个空白: [ ]
keyword后: n个空白+换行(n>=0): [ ]*$
keyword后: 1个空白: [ ]
组合后得到n个单个的条件,使用 | 符号组合这些条件:
key=error
s[0]="^[ ]*" # []中是一个Blank Space和一个TAB,下同
s[1]="[ ]"
e[0]="[ ]*$"
e[1]="[ ]"
s_num=2
e_num=2
# combo the single expression statement
i=0
n=0
while [ $i -lt $s_num ]
do
j=0
while [ $j -lt $e_num ]
do
exp[n]="${s[i]}${key}${e[j]}"
((j=j+1))
((n=n+1))
done
((i=i+1))
done
# combo the regular express
reg_exp=0
k=0
while [ $k -lt $n ]
do
if [ $k -eq 0 ]; then
reg_exp="(${exp[k]})"
else
reg_exp="$reg_exp|(${exp[k]})"
fi
((k=k+1))
done
grep -E "$reg_exp" $file_name
注:
1. []中是一个Blank Space和一个TAB
2. sun下需要使用 /usr/xpg4/bin/grep 代替 grep
39.给系统登录的用户发消息
if [ $(uname) = “AIX” ]; then
OS=”AIX”
else
OS=”OTHER”
fi
list=$(who | awk '{ print $2 }')
for s in $list
do
echo "hi,this is sytem script speaking.bye..." > /dev/$s
done
注: 在AIX下,还可以使用wall命令.
40.输出到stderr
echo “this is error information” > &2