UNIX知识积累

shell个人积累

#目录权限
r 可以列出该目录中的文件
w 可以在该目录中创建或删除文件
x 可以搜索或进入该目录

umask命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最大值分别是6。系统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限。目录则允许设置执行权限,这样针对目录来说, umask中各个数字最大可以到7。

#后台执行命令
cron:系统调度进程。可以使用它在每天的非高峰负荷时间段运行作业,或在一周或一月中的不同时段运行。
At:at命令。使用它在一个特定的时间运行一些特殊的作业,或在晚一些的非负荷高峰时间段或高峰负荷时间段运行。
&:使用它在后台运行一个占用时间不长的进程。
Nohup:使用它在后台运行一个命令,即使在用户退出时也不受影响。在缺省情况下该作业的所有输出都被重定向到一个名为nohup.out的文件中,除非另外指定了输出文件。
在crontab中,每个命令都要给出绝对路径,要保证在shell脚本中提供所有必要的路径和环境变量,除了一些自动设置的全局变量。如果cron不能运行相应的脚本,用户将会收到一个邮件说明其中的原因。

#杀除进程中有关键字abc的一些进程
kill -9 $(ps -ef | grep abc | grep -v grep | awk '{print $2}')

kill -9 $(ps -ef | grep abc | grep -v grep | cut -c 10-14)
#屏幕输出
0表示标准输入,1表示标准输出,2表示错误输出!
cmd>log #表示把cmd的标准输出的信息送到log文件
cmd>/dev/null #表示不输出标准输出,/dev/null表示一个黑洞(也可人为是把标准输出的信息丢弃)
cmd 2>log.err #表示把cmd输出的错误信息送到文件log.err,(此时,正确的输出一样会显示到标准输出设备,例如显示器)
cmd>log 2>&1 #表示cmd的标准输出和错误输出一齐送到文件log
#如何创建一个长度为0的空文件
可以用:>filename 或 touch filename

#重定向操作符command <<delimiter
是一种非常有用的命令,通常都被称为“此处”文挡。shell将分界符delimiter之后直至下一个同样的分界符之前的所有内容都作为输入,遇到下一个分界符,shell就知道输入结束了。这一命令对于自动或远程的例程非常有用。可以任意定义分界符delimiter,最常见的是EOF,而我最喜欢用MAYDAY,这完全取决于个人的喜好。

#命令1 && 命令2
这种命令执行方式相当地直接。&&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功&&那么执
行这个命令”。
#命令1 || 命令2
如果| |左边的命令(命令1)未执行成功,那么就执行| |右边的命令(命令2);或者换句话说,“如果这个命令执行失败了|| 那么就执行这个命令”。
#(命令1;命令2;. . .)
为了在当前shell中执行一组命令,可以用命令分隔符隔开每一个命令,并把所有的命令用圆括号()括起来。
#{命令1;命令2;. . . }
如果使用{ }来代替(),那么相应的命令将在子shell而不是当前shell中作为一个整体被执行,只有在{ }中所有命令的输出作为一个整体被重定向时,其中的命令才被放到子shell中执行,否则在当前shell执行。

登录系统时,在进入命令提示符前,系统要做两个工作。键入用户名和密码后,系统检查是否为有效用户,为此需查询/etc/passwd文件。如果登录名正确并且密码有效,开始下一步过程,即登录环境。登录成功后,系统执行两个环境设置文件,第一个是/etc/profile,第二个是.profile,位于用户根目录下。系统还会处理其他的初始化文件。

设置终端时遇到的一个最普遍问题是退格键不起作用。使用<Ctrl-H>可能会退格并删除前一个字符。
stty erase '^H'

shell将其中任何设置都看做文本字符串。
使用变量时,如果用花括号将之括起来,可以防止shell误解变量值,尽管不必一定要这样做,但这确实可用。
注意,等号两边可以有空格。如果取值包含空格,必须用双引号括起来。shell变量可以用大小写字母。
使用echo命令可以显示单个变量取值,并在变量名前加$
使用unset命令清除变量。
wangnc> bianliang="a"
wangnc> echo $bianliang
a
wangnc> echo ${bianliang}
a
wangnc> unset bianliang
wangnc> echo $bianliang
-bash: bianliang: unbound variable
wangnc>

使用set命令显示所有本地定义的shell变量。
要测试是否已设置或初始化变量。如果未设置或初始化,就可以使用另一值。此命令格式为:${variable:-value}
wangnc> var3=yesyesys
wangnc> echo "test if have ${var3:-nonono}"
test if have yesyesys
wangnc> unset var3
wangnc> echo "test if have ${var3:-nonono}"
test if have nonono
上面的例子并没有将实际值传给变量,需使用下述命令完成此功能:
${variable:=value}
测试变量是否取值,然后返回带有系统错误信息的结果。
wangnc> echo "The file is ${FILES:?"cannt locate variable files"}"
-bash: FILES: cannt locate variable files
如果设置变量时,不想再改变其值,可以将之设置为只读方式。如果有人包括用户本人想要改变它,则返回错误信息。格式如下:
variable-name = value
readonly variable-name
要查看所有只读变量,使用命令readonly即可。

传统上,所有环境变量均为大写。环境变量应用于用户进程前,必须用export命令导出。环境变量与本地变量设置方式相同。
设置环境变量
VARIABLE-NAME = value;export VARIABLE-NAME
在两个命令之间是一个分号,也可以这样写:
VARIABLE-NAME = value
Export VARIABLE-NAME
使用env命令可以查看所有的环境变量。
使用unset命令清除环境变量

在$HOME .profile文件中设置环境变量时,还有另一种方法导出这些变量。使用set命令-a选项,即set -a指明所有变量直接被导出。不要在/etc/profile中使用这种方法,最好只在自己的$HOME .profile文件中使用。

定义的变量如何导出到子进程:
调用子进程前把变量export

如果要向一个shell脚本传递信息,可以使用位置参数完成此功能。参数相关数目传入脚本,此数目可以任意多,但只有前9个可以被访问,使用shift命令可以改变这个限制。参数从第一个开始,在第9个结束;每个访问参数前要加$符号。第一个参数为0,表示预留保存实际脚本名字。无论脚本是否有参数,此值均可用。
注意$ 0返回当前目录路径,如果只返回脚本名,在basename命令下参数设为$0,刚好得到脚本名字。
vi param
------------------------------------------------------
#!/bin/sh
echo "This is the script name:$0"
echo "This is the basename:`basename $0`"
echo "This is the first paramter:$1"
------------------------------------------------------
wangnc> ./param test
This is the script name:./param
This is the basenamearam
This is the first paramter:test

反引号`用于设置系统命令的输出到变量。shell将反引号中的内容作为一个系统命令,并执行其内容。使用这种方法可以替换输出为一个变量。反引号可以与引号结合使用。

假定echo命令加*,意即以串行顺序打印当前整个目录列表,而不是一个星号*
> cd /
> echo *
MANPATH SD_CDROM bin crmdev dev etc home lib lost+found net openboss opt oradata prmdev quseradd sbin stand tmp uniboss usr var
> echo /*
*
>
上述语句同样可用于$$命令,shell解释其为现在进程ID号,使用反斜线屏蔽此意,仅打印$$。
> echo $$
8378
> echo /$$
$$
>

使用命令expr时,用*表示乘法会出现错误,在*前加上反斜线才会正确。
> expr 12*12
12*12
> expr 12/*12
12*12
> expr 12 * 12
expr: syntax error
> expr 12 /* 12
144
>

shift命令的功能:它每次将参数位置向左偏移一位。使用shift命令来处理传递到脚本的每一个参数:
wangnc> pg shifttest
#!/bin/sh
loop=0
while [ $# -ne 0 ]
do
echo $1
shift
done
wangnc> shifttest param1 param2 param3
param1
param2
param3
wangnc>
shift也克服了脚本参数$1..$9的限制。使用shift命令,脚本可以很容易偏移至所有调用参数,因此脚本可以做进一步处理。

<<的用法。当shell看到<<的时候,它就会知道下一个词是一个分界符。在该分界符以后的内容都被当作输入,直到shell又看到该分界符(位于单独的一行)。这个
分界符可以是你所定义的任何字符串。可以使用<<来创建文件、显示文件列表、排序文件列表以及创建屏幕输入。
快速创建一个文件(假如以EOF做结尾,其实任何字符都可以)
wangnc>cat >> newfile <<EOF
> test
> test1
> eof
> EOF
wangnc>pg newfile
test
test1
eof
wangnc>cat >> newfile <<TEST
> haha
> xixi
> TEST
wangnc>pg newfile
test
test1
eof
haha
xixi
wangnc>
如果打开了一个已经存在的文件,输入的内容会附加到该文件的末尾。如果使用tab键,注意,一些老版本的shell可能无法正确理解它的含义。为了解决这一问题,可以在<<之后加一个横杠-,就像下面这样:
cat >> newfile <<-EOF 或 cat <<-EOF

信号就是系统向脚本或命令发出的消息,告知它们某个事件的发生。这些事件通常是内存错误,访问权限问题或某个用户试图停止你的进程。信号实际上是一些数字。下表列出了最常用的信号及它们的含义。
1 SIGHUP 挂起或父进程被杀死
2 SIGINT 来自键盘的中断信号,通常是<CTRL-C>
3 SIGQUIT 从键盘退出
9 SIGKILL 无条件终止
11 SIGSEGV 段(内存)冲突
15 SIGTERM 软件终止(缺省杀进程信号)
在编写shell脚本时,只需关心信号1、2、3和1 5。
trap可以使你在脚本中捕捉信号。该命令的一般形式为:
trap name signal(s)
其中,name是捕捉到信号以后所采取的一系列操作。实际生活中, name一般是一个专门用来处理所捕捉信号的函数。Name需要用双引号(“”)或单引号(‘’)引起来。Signal就是待捕捉的信号。脚本在捕捉到一个信号以后,通常会采取某些行动。最常见的行动包括:
1) 清除临时文件。
2) 忽略该信号。
3) 询问用户是否终止该脚本的运行。
下表列出了一些最常见的trap命令用法:
trap "" 2 3 忽略信号2和信号3,用户不能终止该脚本
trap "commands" 2 3 如果捕捉到信号2或3,就执行相应的commands命令
trap 2 3 复位信号2和3,用户可以终止该脚本
下面的例子一经运行就开始计数直至用户按<Ctrl-C>(信号2)。这时该脚本将会显示出当前的循环数字,然后退出:
wangnc>pg trap1
#!/bin/sh
trap "myexit" 2
LOOP=0
myexit()
{
echo "you just hit <CTRL-C>,at number $LOOP"
echo "i will exit now"
exit 1
}
while :
do
LOOP=`expr $LOOP + 1`
echo $LOOP
done
wangnc>

eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时被称为复杂变量。不过我觉得这些变量本身并不复杂。eval命令也可以用于回显简单变量,不一定是复杂变量。
举例:
wangnc>CAT_PASSWD="cat /etc/passwd | more"
wangnc>echo $CAT_PASSWD
cat /etc/passwd | more
wangnc>eval $CAT_PASSWD
root:dYqRrxaF7RDsA:0:3::/:/sbin/sh
daemon:*:1:5::/:/sbin/sh
bin:*:2:2::/usr/bin:/sbin/sh
sys:*:3:3::/:
...........
wangnc>
if语句测试条件,测试条件返回真(0)或假(1)后,可相应执行一系列语句。if语句结构对错误检查非常有用。其格式为:
if 条件1
then 命令1
elif 条件2
then 命令2
else 命令3
fi
使用if语句时,必须将then部分放在新行,否则会产生错误。如果要不分行,必须使用命令分隔符。本书其余部分将采取这种形式。现在简单if语句变为:
if 条件;then
命令
fi
举例:
wangnc> pg grepstr
#!/bin/sh
echo "Enter a list of names:"
read list
if echo $list | grep "peter" > /dev/null 2>&1
then
echo "peter is here"
else
echo "peter is not in the list"
fi
wangnc>
wangnc> pg iftest2
#!/bin/sh
echo "Enter your name:"
read NAME
if [ "$NAME" = "" ]; then
echo "You did not enter any information!"
fi
wangnc>
wangnc> pg ifparam
#!/bin/sh
if [ $# -lt 3 ]; then
echo "Usage:`basename $0` arg1 arg2 arg3"
exit 1
fi
echo "arg1:$1"
echo "arg2:$2"
echo "arg3:$3"
wangnc>

有时需要知道脚本运行是交互模式(终端模式)还是非交互模式(cron或at)。脚本也许需要这个信息以决定从哪里取得输入以及输出到哪里,使用test命令并带有- t选项很容易确认这一点。如果test返回值为1,则为交互模式。
if [ -t ]; then
echo "we are interactive with a terminal"
else
echo "we must running from some background process probably cron or at"
fi

举例:建目录例子
wangnc> pg ifmkdir
#!/bin/sh
DIR=$1
if [ "$DIR" = "" ]
then
echo "Usage:`basename $0` directory"
exit 1
fi
if [ -d $DIR ]; then
: #do nothing
else
echo "The directory $DIR do not exits!"
echo "Create it noew?[Y|N]"
read YN
if [ "$YN" = "y" ] || [ "$YN" = "Y" ]
then
echo "creating now"
mkdir $DIR >/dev/null 2>&1
if [ $? != 0 ]
then
echo "errors creating the directory $DIR" >&2
exit 1
fi
else
: #do nothing
fi
fi
wangnc>

###################################### case ################################################
case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。case语句格式如下:
case 值 in
模式1)
命令1
...
;;
模式2)
命令2
...
;;
esac
模式部分可能包括元字符,与在命令行文件扩展名例子中使用过的匹配模式类型相同,即:
* 任意字符。
?任意单字符。
[..] 类或范围中任意字符。
举例:
wangnc>pg caseselect
#!/bin/sh
echo "enter a number from 1 to 5:"
read NUM
case $NUM in
1|2) echo "is less then 3"
;;
3) echo "is 3"
;;
4) echo "is 4"
;;
5) echo "is 5"
;;
*) echo "`basename $0`:this is not between 1 and 5" >&2
exit 1
;;
esac
wangnc>

###################################### for ################################################
for循环一般格式为:
for 变量名 in 列表
do
命令1
命令2?
done
举例:
wangnc>pg forloop
#!/bin/sh
for loop in `ls`
do
echo $loop
done
echo "another==========="
for params
do
echo "the param:$params"
done
echo "another==========="
for params in "$@"
do
echo "the param:$params"
done
echo "another==========="
counter=0
for files in *
do
counter=`expr $counter + 1`
done
echo "there are $counter files in `pwd` we need to process"
wangnc>
###################################### until ################################################
until循环格式为:
until 条件
命令1
. . .
done
条件可为任意测试条件,测试发生在循环末尾,因此循环至少执行一次—请注意这一点。
until循环做监视条件也很有用。假定要监视文件系统容量,当它达到一定水平时通知超级用户。
wangnc>pg untilmon
#!/bin/sh
LOOKOUT=`df | grep /home | awk '{print $5}' | sed 's/%//g'`
echo $LOOKOUT
until [ $LOOKOUT -gt 90 ]
do
echo "Filesystem /home is nearly full" | mail root
exit 0
done
wangnc>
###################################### while ################################################
while循环用于不断执行一系列命令,也用于从输入文件中读取数据,其格式为:
while 命令
do
命令1
命令2
. . .
done
虽然通常只使用一个命令,但在while和do之间可以放几个命令。命令通常用作测试条件。
只有当命令的退出状态为0时,do和done之间命令才被执行,如果退出状态不是0,则循环终止。
while循环最常用于从一个文件中读取数据,因此编写脚本可以处理这样的信息。while循环使用输入重定向以保证从文件中读取数据。
wangnc>pg whileread
#!/bin/sh
while read LINE
do
echo $LINE
done < name.txt
wangnc>
对于while循环,只需将空命令直接放在while后,即为无限循环,格式为:
while :
do
命令
done
###################################### continue和break ################################################
break命令允许跳出循环。break通常在进行一些处理后退出循环或case语句。如果是在一个嵌入循环里,可以指定跳出的循环个数。例如如果在两层循环内,用break 2刚好跳出整个循环。
continue命令类似于break命令,只有一点重要差别,它不会跳出循环,只是跳过这个循环步。

测试文件状态
test一般有两种格式,即:
test condition

[ condition ]
使用方括号时,要注意在条件两边加上空格。
测试文件状态的条件表达式很多,但是最常用:
-d 目录
-s 文件长度大于0、非空
-f 正规文件
-w 可写
-L 符号连接
-u 文件有suid位设置
-r 可读
-x 可执行
0表示成功,其他为失败。
举例:
wangnc> ll data.f
-rw-rw-r-- 1 wangnc users 254 Aug 21 16:33 data.f
wangnc> [ -w data.f ]
wangnc> echo $?
0
wangnc> test -w data.f
wangnc> echo $?
0
wangnc> [ -x data.f ]
wangnc> echo $?
1
wangnc>
shell提供三种逻辑操作完成此功能。
-a 逻辑与,操作符两边均为真,结果为真,否则为假。
-o 逻辑或,操作符两边一边为真,结果为真,否则为假。
! 逻辑否,条件为假,结果为真。
举例:
wangnc> ll data.f hehe.txt
-rw-rw-r-- 1 wangnc users 254 Aug 21 16:33 data.f
-rw-rw-r-- 1 wangnc users 0 Aug 18 15:32 hehe.txt
wangnc> [ -w data.f -a -r hehe.txt ]
wangnc> echo $?
0
wangnc>

字符串测试
字符串测试有5种格式。
test "string"
test string_operator "string"
test "string" string_operator "string"
test [ string_operator string ]
test [ string string_operator string ]
这里,string_operator可为:
= 两个字符串相等。
!= 两个字符串不等。
-z 空串。
-n 非空串。
举例:
wangnc> [ -z $EDITOR ]
wangnc> echo $?
1
wangnc> [ $EDITOR = "vi" ]
wangnc> echo $?
0
wangnc> echo $EDITOR
vi
wangnc> var1="hehe"
wangnc> var2="haha"
wangnc> [ "$var1" = "$var2" ]
wangnc> echo $?
1
wangnc>

测试数值
测试数值可以使用许多操作符,一般格式如下:
"number" numeric_operator "number"
或者
[ "number" numeric_operator "number" ]
numeric_operator可为:
-eq 数值相等。
-ne 数值不相等。
-gt 第一个数大于第二个数。
-lt 第一个数小于第二个数。
-le 第一个数小于等于第二个数。
-ge 第一个数大于等于第二个数。
举例:
wangnc>NUMBER=130
wangnc>[ "$NUMBER" -eq 130 ]
wangnc>echo $?
0
wangnc>[ $NUMBER -eq 130 ]
wangnc>echo $?
0
wangnc>[ $NUMBER -eq 10 ]
wangnc>echo $?
1
wangnc>[ $NUMBER -gt 10 ]
wangnc>echo $?
0
wangnc>

expr用法
expr命令一般用于整数值,但也可用于字符串。一般格式为:
expr argument operator argument
expr也是一个手工命令行计数器。
举例:
wangnc>expr 10+10
10+10
wangnc>expr 10 + 10
20
wangnc>expr 10 / 2
5
wangnc>expr 10 * 2
expr: syntax error
wangnc>expr 10 /* 2
20
wangnc>
expr也有模式匹配功能。可以使用expr通过指定冒号选项计算字符串中字符数。. *意即任何字符重复0次或多次。
wangnc>VALUE=accounts.doc
wangnc>expr $VALUE:'/(.*/).doc'
accounts.doc:/(.*/).doc
wangnc>expr $VALUE : '/(.*/).doc'
accounts
wangnc>
有必要知道脚本运行时的一些相关控制信息,这就是特定变量的由来。共有7个特定变量:
$# 传递到脚本的参数个数
$* 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的进程ID号
$@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
$- 显示shell使用的当前选项,与set命令功能相同
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
vi param
------------------------------------------------------
#!/bin/sh
echo "This is the script name:$0"
echo "This is the basename:`basename $0`"
echo "This is the first paramter:$1"
echo "This is the second paramter:$2"
echo "The number of arguments:$#"
echo "Show all arguments:$*"
echo "Show my process ID:$$"
echo "Show the the arguments in quotes:$@"
echo "Did my script go with my errors:$?"
------------------------------------------------------

Brourne shell 有一些预留的环境变量名,这些变量名不能用作其他用途。通常在/etc/ p r o f i l e中建立这些嵌入的环境变量,但也不完全是,这取决于用户自己。以下是嵌入shell变量列表。
CDPATH 改变目录路径变量,保留一系列由冒号隔开的路径名,用于c d命令
EXTINIT 保存使用v i编辑器时的初始化选项
HOME 通常定位于passwd文件的倒数第2列,用于保存用户自身文件。
IFS 用作shell指定的缺省域分隔符。
LOGNAME 变量保存登录名
MAIL 保存邮箱路径名,缺省为/var/spool/mail/<login name>。
MAILCHECK 缺省每60s检查新邮件
MAILPATH 如果有多个邮箱要用到MAILPATH,此变量设置将覆盖MAIL设置。
PATH 保存进行命令或脚本查找的目录顺序
PS1 基本提示符包含shell提示符,缺省对超级用户为#,其他为$。可以使用任何符号作提示符
PS2 为附属提示符,缺省为符号>。PS2用于执行多行命令或超过一行的一个命令。
SHELL 保存缺省shell,通常在/etc/passwd中已设置
TERMINFO 终端初始化变量保存终端配置文件的位置
TERM 保存终端类型
TZ 时区变量保存时区值,只有系统管理员才可以更改此设置

IFS用作shell指定的缺省域分隔符。原理上讲域分隔符可以是任意字符,但缺省通常为空格、新行或tab键。IFS在分隔文件或变量中各域时很有用。下面的例子将IFS设置为冒号,然后echo PATH变量,给出一个目录分隔开来的可读性很强的路径列表。
要设置其返回初始设置:
$IFS=<space><tab>; export IFS
这里<space><tab>为空格和tab键。

还有一些预留的环境变量。其他系统或命令行应用将用到它们。以下是最常用的一些,注意这些值均未有缺省设置,必须显示说明。
EDITOR 设置编辑器,最常用。
PWD 当前目录路径名,用cd命令设置此选项。
PAGER 保存屏幕翻页命令,如pg、more,在查看man文本时用到此功能
MANPATH 保存系统上man文本的目录。目录间用冒号分隔。
LPDEST或PRINTER 保存缺省打印机名,用于打印作业时指定打印机名。

:空,永远返回为true
. 从当前shell中执行操作
break 退出for、while、until或case语句
cd 改变到当前目录
continue 执行循环的下一步
echo 反馈信息到标准输出
eval 读取参数,执行结果命令
exec 执行命令,但不在当前shell
exit 退出当前shell
export 导出变量,使当前shell可利用它
pwd 显示当前目录
read 从标准输入读取一行文本
readonly 使变量只读
return 退出函数并带有返回值
set 控制各种参数到标准输出的显示
shift 命令行参数向左偏移一个
test 评估条件表达式
times 显示shell运行过程的用户和系统时间
trap 当捕获信号时运行指定命令
ulimit 显示或设置shell资源
umask 显示或设置缺省文件创建模式
unset 从shell内存中删除变量或函数
wait 等待直到子进程运行完毕,报告终止

当测试一段脚本且脚本包含参数时,这样使用set命令有很多用处。其一就是不必在每次运行脚本时重复输入参数。
wangnc>pg setex
#!/bin/sh
set hehe.txt haha.log
while [ $# != 0 ]
do
echo $1
shift
done
wangnc>setex
hehe.txt
haha.log
wangnc>

times命令给出用户脚本或任何系统命令的运行时间。第一行给出shell消耗时间,第二行给出运行命令消耗的时间。
wangnc>times
0m0.030s 0m0.110s
0m0.390s 0m0.290s
wangnc>

使用type查询命令是否仍驻留系统及命令类型。
wangnc>type cp
cp is aliased to `cp -i'
wangnc>type pwd
pwd is a shell builtin
wangnc>

ulimit设置运行在shell上的显示限制。通常此命令定位于文件/etc/profile中,但是可以从当前shell或用户.profile文件中将之移入用户需要的位置。
wangnc>ulimit -a
core file size (blocks, -c) 2097151
data seg size (kbytes, -d) 1048576
file size (blocks, -f) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 2048
pipe size (512 bytes, -p) 16
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 1025
virtual memory (kbytes, -v) unlimited
wangnc>

wait命令等待直到一个用户子进程完成,可以在wait命令中指定进程ID号。如果并未指定,则等待直到所有子进程完成。

我们如何指定使用那一个Shell 来解释所写的Script呢?几种基本的指定方式如下所述:
1. 如果Script的第一个非空白字元不是"#",则它会使用Bourne Shell。
2. 如果Script的第一个非空白字元是"#"时,但不以"#!"开头时,则它会使用C Shell。
3. 如果Script以"#!"开头,则"#!"後面所写的就是所使用的Shell,而且要将整个路径名称指出来。
这里建议使用第三种方式指定Shell ,以确保所执行的就是所要的。Bourne Shell的路径名称为/bin/sh ,而C Shell 则为/bin/csh。
跟踪错误的最好方式是亲自查阅脚本,并使用set命令并加大量的echo语句。
set命令可辅助脚本调试。以下是set命令常用的调试选项:
set -n 读命令但并不执行。
set -v 显示读取的所有行。
set -x 显示所有命令及其参数。
将set选项关闭,只需用+替代-。有人总认为+应该为开,而-应为关闭,但实际刚好相反。
举例:
wangnc>pg whileread
#!/bin/sh
set -x
while read LINE
do
echo $LINE
done < name.txt
set +x
wangnc>whileread
+ 0< name.txt
+ read LINE
+ echo M.Golls 12 Hidd Rd
M.Golls 12 Hidd Rd
+ read LINE
+ echo P.Heller The Acre
P.Heller The Acre
+ read LINE
+ echo P.Willey 132 The Grove
P.Willey 132 The Grove
+ read LINE
+ echo T.Norms 84 Connaught Rd
T.Norms 84 Connaught Rd
+ read LINE
+ echo K.Fletch 12 Woodlea
K.Fletch 12 Woodlea
+ read LINE
wangnc>

定义函数的格式为:
函数名()
{
命令1
. . .
}
或者
函数名(){
命令1
. . .
}
两者方式都可行。如果愿意,可在函数名前加上关键字function,这取决于使用者。
function 函数名()
{ ...
}
所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

向函数传递参数就像在一般脚本中使用特殊变量$1,$2...$9一样,函数取得所传参数后,将原始参数传回shell脚本,因此最好先在函数内重新设置变量保存所传的参数。这样如果函数有一点错误,就可以通过已经本地化的变量名迅速加以跟踪。函数里调用参数(变量)的转换以下划线开始,后加变量名,如: _FILENAME或_ filename。
当函数完成处理或希望函数基于某一测试语句返回时,可做两种处理:
1) 让函数正常执行到函数末尾,然后返回脚本中调用函数的控制部分。
2) 使用return返回脚本中函数调用的下一条语句,可以带返回值。0为无错误,1为有错误。这是可选的,与最后状态命令报表例子极其类似。其格式为:
return 从函数中返回, 用最后状态命令决定返回值。
Return 0 无错误返回。
Return 1 有错误返回

举例:编写函数文件-定位文件(. filename)-检查载入函数(set)-执行函数-删除函数(unset)-修改函数-重定位文件(. filename)-检查载入函数(set)-执行函数
wangnc> pg functions.main
#!/bin/sh
findit()
{
if [ $# -lt 1 ]; then
echo "Usage:findit filename"
return 1
fi
find . -name $1 -print
}
wangnc> . functions.main
wangnc> set
......
UID=135
_=/functions.main
findit ()
{
if [ $# -lt 1 ]; then
echo "Usage:findit filename";
return 1;
fi;
find . -name $1 -print
}
wangnc> findit
Usage:findit filename
wangnc> findit hehe.txt
./hehe.txt
wangnc>unset findit
wangnc>set
......
UID=135
_=findit
wangnc>pg functions.main
#!/bin/sh
findit()
{
if [ $# -lt 1 ]; then
echo "Usage:findit filename"
return 1
fi
for loop
do
find . -name $loop -print
done
}
wangnc>. functions.main
wangnc>set
......
UID=135
_=functions.main
findit ()
{
if [ $# -lt 1 ]; then
echo "Usage:findit filename";
return 1;
fi;
for loop in "$@";
do
find . -name $loop -print;
done
}
wangnc>findit hehe.txt data.f
./hehe.txt
./data.f
wangnc>

从函数文件中调用函数
将公用函数放入函数文件functions.sh里,编写脚本就可以调用functions.sh中的函数了。注意函数文件在脚本中以下述命令格式定位:
. /<path to file>
使用这种方法不会创建另一个shell,所有函数均在当前shell下执行。就是说在新shell文件中定位文件(. functions.sh)后,就可以直接使用这些函数了。同时这种方法还可以定义公用配置文件。
举例:
wangnc> pg backfunc
#!/bin/sh
#config info
_CODE="comet"
_DIRNAME="test"
_LOGFILE="/crmdev/wangnc/test"
#public functions
IsDir()
{
if [ $# -lt 1]; then
echo "IsDir:I need a dir name"
return 1
fi
DIRNAME=$1
if [ ! -d $DIRNAME ]; then
return 1;
else
return 0;
fi
}
wangnc> pg readfunc
#!/bin/sh
if [ -r backfunc ]; then
#source the file
. ./backfunc
else
echo "`basename $0` cannot locate backfunc file"
fi
echo "Enter the code name:"
read CODE
if [ "$CODE" != "$_CODE" ]; then
echo "wrong code.exiting.will use defaults"
exit 1
else
: #do nothing
fi
if IsDir $_DIRNAME; then
echo "$_DIRNAME is a directory"
fi
echo "The logfile is:$_LOGFILE"
wangnc> readfunc
Enter the code name:
test
wrong code.exiting.will use defaults
wangnc> readfunc
Enter the code name:
comet
./readfunc[4]: test: A ] character is missing.
test is a directory
The logfile is:/crmdev/wangnc/test
wangnc>

 

awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

有三种方式调用awk,第一种是命令行方式,如:
awk [-F field-separator] 'commands' input-file(s)
这里,commands是真正的awk命令。本章将经常使用这种方法。上面例子中,[ - F域分隔符]是可选的,因为awk使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明- F选项,如:awk -F: 'commands' input-file
第二种方法是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
第三种方式是将所有的awk命令插入一个单独文件,然后调用:awk -f awk-script-file input-file(s)
-f选项指明在文件awk_script_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名。
awk执行时,其浏览域标记为$1,$2...$n。这种方法称为域标识。但不要忘了加逗号以分隔域。如果希望打印一个有5个域的记录的所有域可使用$0,意即所有域。
确保用花括号括起动作语句(如print这种动作),用圆括号括起条件语句。正则表达式用斜线//括起来。注意分号的使用,它分隔awk命令。

vi data.f(每列后是tab)
48 Dec 3BC1997 LPSX 68.00 LVX2A 138
483 Sept 5Ap1996 USP 65.00 LVX2C 189
47 Oct 3ZL1998 LPSX 43.00 KVM9D 512
219 dec 2CC1999 CAD 23.00 PLV2C 68
484 nov 7PL1996 CAD 49.00 PLV2C 234
483 may 5PA1998 USP 37.00 KVM9D 644
216 sept 3ZL1998 USP 86.00 KVM9E 234

下面的例子重定向输出到新文件:
awk '{print $0}' data.f > data.f.1
使用t e e命令,在输出到文件的同时输出到屏幕:
awk '{print $0}' data.f | tee data.f.2
打印信息头放置在B E G I N模式部分:
awk 'BEGIN {print "Name Belt/n---------------"}{print $1"/t"$4}' data.f
打印信息尾。E N D语句在所有文本处理动作执行完之后才被执行。E N D语句在脚本中的位置放置在主要动作之后:
awk 'BEGIN {print "Name Belt/n---------------"}{print $1"/t"$4} END {print "end-of-report"}' data.f
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用i f语句。awk中i f后面的条件用()括起来。
如果第1域匹配483的话就把该记录打印出来:
awk '{if($1~/483/) print $0}' data.f
完成同一目的也可以这样写:
awk '$0~/483/' data.f
为精确匹配4 8,使用等号= =,并用单引号括起条件:
awk '{if($1=="48") print $0}' data.f
有时要浏览信息并抽取不匹配操作的记录,与~相反的符号是!~,意即不匹配:
awk '{if($1!~/483/) print $0}' data.f
完成同一目的也可以这样写:(缺省情况下, awk将打印所有匹配记录)
awk '$0!~/483/' data.f
为查询大小写信息,可使用[ ]符号。在测试正则表达式时提到可匹配[ ]内任意字符或单词:
awk '/[lL]PSX/' data.f
抽取名字,其记录第3域的第3个字符是L,使用句点.
awk '$3~/^..L/' data.f
使用竖线符|意为匹配| 两边模式之一。注意,使用竖线符时,语句必须用圆括号括起来:
awk '$0~/(USP|LPSX)/' data.f
复合表达式,&& AND,|| OR,!非:
awk '{if($1=="483" && $2~/^Sept/) print $0}' data.f

awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行-F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
要快速查看记录个数,应使用NR。print NR放在E N D语法中:
awk 'END {print NR}' data.f
使用NF变量显示每一条读记录中有多少个域,并在END部分打印输入文件名:
awk '{print NR,NF,$0}END{print FILENAME}' data.f
至少存在一个记录后,查询字符串USP,最后打印结果:
awk '{if(NR>0&&$4~/USP/)print$0}' data.f
NF的一个强大功能是将变量$PWD的返回值传入awk并显示其目录。这里需要指定域分隔符/
echo $PWD | awk -F/ '{print $NF}'

设置输入域到域变量名:
awk '{no=$1;month=$2;if(no=="48") print no" month is " month}' data.f
修改数值域取值:
awk '{if($1=="48") $5=$5-10; print $1,$5,$6}' data.f
修改文本域:(要记住实际输入文件是不可修改的,修改的只是保存在缓存里的awk复本。awk会在变量N R或N F变量中反映出修改痕迹。)
awk '{if($2=="Dec") $2="December";print $0}' data.f
只显示修改记录:
awk '{if($2=="Dec") {$2="December";print $0}}' data.f
创建新的输出域:
awk 'BEGIN {print "No/tMonYear"} {if($2~/[Ss]ept/) {$8=$5-$7; print $2,$8}}' data.f
awk 'BEGIN {print "No/tMonYear"} {if($2~/[Ss]ept/) {diff=$5-$7; print $2,diff}}' data.f
列值增加很有用。许多文件都要求统计总数:
awk '(tol+=$5); END {print "Total money:" tol}' data.f
如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上大括号{}即可:
awk '{(tol+=$5)}; END {print "Total money:" tol}' data.f
快速查看所有文件的长度及其总和,但要排除子目录:
ls -l | awk '/^[^d]/ {print $9"/t"$5} {tol+=$5} END {print "Total KB:"tol}'

awk内置字符串函数
gsub(r,s) 在整个$0中用s替代r
gsub(r,s,t) 在整个t中用s替代r
index(s,t) 返回s中字符串t的第一位置
length(s) 返回s长度
match(s,r) 测试s是否包含匹配r的字符串
split(s,a,fs) 在fs上将s分成序列a
sprint(fmt,exp) 返回经fmt格式化后的exp
sub(r,s) 用$0中最左边最长的子串代替s
substr(s,p) 返回字符串s中从p开始的后缀部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分
要在整个记录中替换一个字符串为另一个,使用正则表达式格式, /目标模式/,替换模式/
awk 'gsub(/483/,111) {print $0}' data.f
返回目标字符串Bunny中ny出现的第一位置,即字符个数
awk 'BEGIN {print index("Bunny","ny")}'

观察ASCII码中65的等价值。管道输出65到awk。printf进行ASCII码字符转换。这里也加入换行,因为缺省情况下printf不做换行动作:
echo "65" | awk '{printf "%c/n",$0}' 或 awk 'BEGIN {printf "%c/n",65}' 效果一样
整数传入后被加了六个小数点:
awk 'BEGIN {printf "%f/n",999}'
要求名字左对齐,15个字符长度,后跟序列号:
awk '{printf "%-15s%s/n",$2,$1}' data.f

awk脚本文件
脚本从/etc/passwd文件中抽取第1和第5域,通过分号“;”分隔passwd文件域。第1域是帐号名,第5域是帐号所有者。
vi passwd.awk
-------------------------------------------------------------------
#!/bin/awk -f
#to call: passwd.awk /etc/passwd
BEGIN{FS=":"}
{print $1,"/t",$5}
-------------------------------------------------------------------
chmod u+x passwd.awk
passwd.awk /etc/passwd

cut用来从标准输入或文本文件中剪切列或域。剪切文本可以将之粘贴到一个文本文件。
cut一般格式为:
cut [options] file1 file2
下面介绍其可用选项:
-c list 指定剪切字符数。
-f field 指定剪切域数。
-d 指定与空格和tab键不同的域分隔符。
-c 用来指定剪切范围,如下所示:
-c1,5-7 剪切第1个字符,然后是第5到第7个字符。
-c1-50 剪切前50个字符。
-f 格式与-c相同。
-f1,5 剪切第1域,第5域。
-f1,10-12 剪切第1域,第10域到第12域。

例子:
wangnc> pg pers
P.Jones:Office Runner:ID897
S.Round:UNIX admin:ID666
L.Clip:Personl Chief:ID982

文件中使用冒号“:”为域分隔符,故可用- d选项指定冒号,如-d:。如果有意观察第3域,可以使用-f3。要抽取ID域。可使用命令如下:
wangnc> cut -d: -f3 pers
ID897
ID666
ID982

cut命令中剪切各域需用逗号分隔,如剪切域1和3,即名字和ID号,可以使用:
wangnc> cut -d: -f1,3 pers
P.Jones:ID897
S.Round:ID666
L.Clip:ID982
使用-c选项指定精确剪切数目。这种方法需确切知道开始及结束字符。通常我不用这种方法,除非在固定长度的域或文件名上。
who -u | cut -c1-8

cut用来从文本文件或标准输出中抽取数据列或者域,然后再用paste可以将这些数据粘贴起来形成相关文件。
粘贴两个不同来源的数据时,首先需将其分类,并确保两个文件行数相同。paste将按行将不同文件行信息放在一行。缺省情况下, paste连接时,用空格或tab键分隔新行中不同文本,除非指定-d选项,它将成为域分隔符。
paste格式为:
paste -d -s -file1 file2
选项含义如下:
-d 指定不同于空格或tab键的域分隔符。例如用@分隔域,使用- d @。
-s 将每个文件合并成行而不是按行粘贴。
- 使用标准输入。例如ls -l |paste ,意即只在一列上显示输出。

例子:
wangnc> pg pas1
ID897
ID666
ID982
wangnc> pg pas2
P.Jones
S.Round
L.Clip

基本paste命令将pas1和pas2两文件粘贴成两列:
wangnc> paste pas1 pas2
ID897 P.Jones
ID666 S.Round
ID982 L.Clip

通过交换文件名即可指定哪一列先粘:
wangnc> paste pas2 pas1
P.Jones ID897
S.Round ID666
L.Clip ID982

要创建不同于空格或tab键的域分隔符,使用-d选项。下面的例子用冒号做域分隔符。
wangnc> paste -d: pas2 pas1
P.Jones:ID897
S.Round:ID666
L.Clip:ID982

要合并两行,而不是按行粘贴,可以使用-s选项。下面的例子中,第一行粘贴为名字,第二行是ID号。
wangnc> paste -s pas1 pas2
ID897 ID666 ID982
P.Jones S.Round L.Clip

paste命令还有一个很有用的选项(-)。意即对每一个(-),从标准输入中读一次数据。使用空格作域分隔符,以一个4列格式显示目录列表。方法如下:
wangnc> ls /etc | paste -d" " - - - - - -
MANPATH PATH SHLIB_PATH SnmpAgent.d/ TIMEZONE X11/
acct/ aliases@ arp@ audeventstab audomon@ auto_master
auto_parms.log auto_parms.log.old backup@ backup.cfg bcheckrc@ bootpd@
bootpquery@ bootptab btmp@ catman@ checklist@ chroot@
clri@ cmcluster/ cmcluster.conf cmom.conf conf@ convertfs@
copyright cron@ csh.login d.cshrc@ d.exrc@ d.login@
也可以以一列格式显示输出:
wangnc> ls /etc | paste -d"" -
MANPATH
PATH
SHLIB_PATH
SnmpAgent.d/
TIMEZONE
X11/
acct/
aliases@
arp@
audeventstab
audomon@
auto_master
auto_parms.log
auto_parms.log.old
backup@
backup.cfg

#find命令
在自己的根目录$HOME中查找文件名符合*.txt的文件,波浪号~代表了你的$HOME目录。记住要用引号将文件名模式引起来!
find ~ -name "*.log" -print
想要的当前目录(及子目录中)和/etc目录中查找文件名以一个大写字母开头的文件,可以用:
find . /etc -name "[A-Z]*" -print
想要查找$HOME目录中的文件,可以用:
find ~ -name "*" -print 或 find . -print
要想让系统高负荷运行,就从根目录开始查找所有的文件。
find / -name "*" -print
为了在当前目录下查找文件权限位为7 5 5的文件,即文件属主可以读、写、执行,其他用户可以读、执行的文件,可以用:
find . -perm 755 -print
如果希望在当前目录下查找所有用户都可读、写、执行的文件(要小心这种情况),在八进制数字前面要加一个横杠-。
find . -perm -007 -print
如果希望在/apps目录下查找文件,但不希望在/apps/bin目录下查找,可以用:
find /apps -name "/apps/bin" -prune -o -print
在$HOME目录中查找文件属主为d a v e的文件,可以用:
find ~ -user dave -print
为了查找属主帐户已经被删除的文件,可以使用- nouser选项。这样就能够找到那些属主在/etc/passwd文件中没有有效帐户的文件。
find /home -nouser -print
为了在/apps目录下查找属于accts用户组的文件,可以用:
find /apps -group accts -print
要查找没有有效所属用户组的所有文件,可以使用nogroup选项。
find / -nogroup -print
希望在系统根目录下查找更改时间在5日以内的文件,可以用:
find / -mtime -5 -print
为了在/ v a r / a d m目录下查找更改时间在3日以前的文件,可以用:
find /var/adm -mtime +3 -print
下面给出的f i nd命令能够查找更改时间比文件script.log新但比文件script_new.log旧的文件:
find ~ -newer script.log ! -newer script_new.log -exec ls -l {} /;
假设现在的时间是23:40,希望查找更改时间在两个小时以内的文件,可以首先创建这样一个文件:
touch -t 05042140 hehe.txt
一个符合要求的文件已经被创建;这里我们假设今天是五月四日,而该文件的更改时间是2 1 : 4 0,比现在刚好早两个小时。
现在我们就可以使用f i n d命令的-newer选项在当前目录下查找所有更改时间在两个小时以内的文件:
find . -newer hehe.txt -print
如果要在/etc目录下查找所有的目录,可以用:
find /etc -type d -print
为了在当前目录下查找除目录以外的所有类型的文件,可以用:
find . ! -type d -print
为了在/ e t c目录下查找所有的符号链接文件,可以用:
find /etc -type l -print
为了在当前目录下查找文件长度大于1 M字节的文件,可以用:
find . -size +1000000c -print
为了在/home/apache目录下查找文件长度恰好为100字节的文件,可以用:
find /home/apache -size 100c -print
为了在当前目录下查找长度超过10块的文件(一块等于512字节),可以用:
find . -size +10 -print
从文件系统的根目录开始,查找一个名为CON.FILE的文件。它将首先匹配所有的文件然后再进入子目录中查找。
find / -name "CON.FILE" -depth -print
从当前目录开始查找位于本文件系统中文件名以XC结尾的文件:
find . -name "*.XC" -mount -print
在当前目录中查找所有文件名以. LOG结尾、更改时间在1日以上的文件,并删除它们,只不过在删除之前先给出提示(使用-ok)。
find . -name "*.log" -mtime +1 -ok rm {} /;
按y键删除文件,按n键不删除。
为了查找系统中所有文件长度为0的普通文件,并列出它们的完整路径,可以用:
find / -type f -size 0 -exec ls -l {} /;
为了查找当前文件系统中的所有目录并排序,可以用:
find . -type d -print -local |sort
使用-exec选项会为处理每一个匹配到的文件而发起一个相应的进程,并非将匹配到的文件全部作为参数一次执行;这样在有些情况下就会出现进程过多,系统性能下降的问题,因而效率不高;而使用xargs命令则只有一个进程。另外,在使用xargs命令时,究竟是一次获取所有的参数,还是分批取得参数,以及每一次获取参数的数目都会根据该命令的选项及系统内核中相应的可调参数来确定。
在/apps/audit目录下查找所有用户具有读、写和执行权限的文件,并收回相应的写权限:
find /apps/audit -perm -7 -print | xargs chmod o-w

#grep命令
在grep命令中输入字符串参数时,最好将其用双引号括起来。例如:“mystring”。这样做有两个原因,一是以防被误解为shell命令,二是可以用来查找多个单词组成的字符串。在调用变量时,也应该使用双引号,诸如: grep“$MYVAR”文件名,如果不这样,将没有返回结果。在调用模式匹配时,应使用单引号。
常用的grep选项有:
-c 只输出匹配行的计数。
-i 不区分大小写(只适用于单字符)。
-h 查询多文件时不显示文件名。
-l 查询多文件时只输出包含匹配字符的文件名。
-n 显示匹配行及行号。
-s 不显示不存在或无匹配文本的错误信息。
-v 显示不包含匹配文本的所有行。
vi data.f(每列后是tab)
48 Dec 3BC1997 LPSX 68.00 LVX2A 138
483 Sept 5Ap1996 USP 65.00 LVX2C 189
47 Oct 3ZL1998 LPSX 43.00 KVM9D 512
219 dec 2CC1999 CAD 23.00 PLV2C 68
484 nov 7PL1996 CAD 49.00 PLV2C 234
483 may 5PA1998 USP 37.00 KVM9D 644
216 sept 3ZL1998 USP 86.00 KVM9E 234
结合使用^和$可查询空行。使用-n参数显示实际行数:
grep -n '^$' data.f
grep允许使用国际字符模式匹配或匹配模式的类名形式:
类 等价的正则表达式
[[:upper:]] [A-Z]
[[:alnum:]] [0-9a-zA-Z]
[[:lower:]] [a-z]
[[:space:]] 空格或tab键
[[:digit:]] [0-9]
[[:alpha:]] [a-zA-Z]
如:grep '5[[:upper:]][[:upper:]]' data.f
如果要查询目录列表中的目录,方法如下:
ls -l | grep '^d'
如果在一个目录中查询不包含目录的所有文件,方法如下:
ls -l | grep '^[^d]'
要查询其他用户和其他用户组成员有可执行权限的目录集合,方法如下:
ls -l | grep '^d.....x..x'
使用grep命令- s开关,可屏蔽错误信息。
wangnc> grep "test" fdasf.f
grep: can't open fdasf.f
wangnc> grep -s "test" dafds.f
wangnc>
egrep代表expression或extended grep,适情况而定。egrep接受所有的正则表达式,egrep的一个显著特性是可以以一个文件作为保存的字符串,然后将之传给egrep作为参数,为此使用- f开关。
wangnc> vi testfile
wangnc> pg testfile
484
47
wangnc> egrep -f testfile data.f
47 Oct 3ZL1998 LPSX 43.00 KVM9D 512
484 nov 7PL1996 CAD 49.00 PLV2C 234
如果要查询存储代码32L或2CC,可以使用(|)符号,意即“|”符号两边之一或全部。
egrep '(3ZL|2CC)' data.f
join用来将来自两个分类文本文件的行连在一起。下面讲述join工作方式。这里有两个文件file1和file2,当然已经分类。每个文件里都有一些元素与另一个文件相关。由于这种关系,join将两个文件连在一起,这有点像修改一个主文件,使之包含两个文件里的共同元素。文本文件中的域通常由空格或tab键分隔,但如果愿意,可以指定其他的域分隔符。类似于数据库中的join。
其一般格式为:
join [options] input-file1 input-file2
让我们看看它的可用选项列表:
an n为一数字,用于连接时从文件n中显示不匹配行。例如, -a1显示第一个文件的不匹配行,-a2为从第二个文件中显示不匹配行。
o n.m n为文件号,m为域号。1.3表示只显示文件1第三域,每个n,m必须用逗号分隔,如1.3,2.1。
j n m n为文件号,m为域号。使用其他域做连接域。
t 域分隔符。用来设置非空格或tab键的域分隔符。例如,指定冒号做域分隔符-t:
例子:
wangnc> pg name.txt
M.Golls 12 Hidd Rd
P.Heller The Acre
P.Willey 132 The Grove
T.Norms 84 Connaught Rd
K.Fletch 12 Woodlea
wangnc> pg town.txt
M.Golls Norwich NRD
P.Willey Galashiels GDD
T.Norms Brandon BSL
K.Fletch Mildenhall MAF
wangnc>
连接两个文件,使得名字支持详细地址。例如M . G o l l s记录指出地址为12 Hidd Rd。连接域为域0—名字域。因为两个文件此域相同, join将假定这是连接域:
wangnc> join name.txt town.txt
M.Golls 12 Hidd Rd Norwich NRD
P.Willey 132 The Grove Galashiels GDD
T.Norms 84 Connaught Rd Brandon BSL
K.Fletch 12 Woodlea Mildenhall MAF
好,工作完成。缺省join删除或去除连接键的第二次重复出现,这里即为名字域。
如果一个文件与另一个文件没有匹配域时怎么办?这时join不可以没有参数选项,经常指定两个文件的- a选项。下面的例子显示匹配及不匹配域。
wangnc> join -a1 -a2 name.txt town.txt
M.Golls 12 Hidd Rd Norwich NRD
P.Heller The Acre
P.Willey 132 The Grove Galashiels GDD
T.Norms 84 Connaught Rd Brandon BSL
K.Fletch 12 Woodlea Mildenhall MAF
使用- o选项选择连接域。例如要创建一个文件仅包含人名及城镇, join执行时需要指定显示域。方式如下:
使用1 . 1显示第一个文件第一个域,2 . 2显示第二个文件第二个域,其间用逗号分隔。命令为:
wangnc> join -o 1.1,2.2 name.txt town.txt
M.Golls Norwich
P.Willey Galashiels
T.Norms Brandon
K.Fletch Mildenhall
使用-jn m进行其他域连接,例如用文件1域3和文件2域2做连接键,命令为:
join -j1 3 -j2 2 file1 file2
使用join应注意连接域到底是哪一个,比如说你认为正在访问域4,但实际上join应该访问域5,这样将不返回任何结果。如果是这样,用awk检查域号。
例如,键入$awk '{print $4}'文件名,观察其是否匹配假想域。

sed是一个强大的文本过滤工具。使用sed可以从文件或字符串中抽取所需信息。
sed是一个非交互性文本流编辑器。它编辑文件或标准输入导出的文本拷贝。Vi也是一个文本编辑器。sed可以随意编辑小或大的文件,有许多sed命令用来编辑、删除,并允许做这项工作时不在现场。sed一次性处理所有改变,因而变得很有效,对用户来讲,最重要的是节省了时间。使用sed需要记住的一个重要事实是,无论命令是什么, sed并不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件,将输出到屏幕。
打印第2行:(p表示显示行,-n表示只显示匹配行)
sed -n '2p' data.f
现打印1到3行,用逗号分隔行号:
sed -n '1,3p' data.f
模式匹配行:
sed -n '/USP/'p data.f 同 awk '$0~/USP/' data.f
使用4,/USP/。意即只在第四行查询模式the:???
sed -n '4,/USP/'p data.f
要打印整个文件,只需将行范围设为第一行到最后一行1 , $。$意为最后一行:
sed -n '1,$p' data.f
要打印文件第一行,使用行号:
sed -n '1p' data.f
要打印最后一行,使用$。$是代表最后一行的元字符:
sed -n '$p' data.f
要打印行号,使用等号=。打印模式匹配的行号,使用格式/pattern/ =
sed -n '/USP/=' data.f
打印模式匹配的行号及其所有内容,使用-e
sed -e '/USP/=' data.f
如果只打印行号及匹配行,必须使用两个sed命令,并使用e选项。第一个命令打印模式匹配行,第二个使用=选项打印行号,格式为sed -n -e /pattern/p -e /pattern/=
sed -n -e '/USP/p' -e '/USP/=' data.f

sort命令的一般格式为:
sort -cmu -o output_file [other options] +pos1 +pos2 input_files
下面简要介绍一下sort的参数:
-c 测试文件是否已经分类。
-m 合并两个分类文件。
-u 删除所有复制行。
-o 存储sort结果的输出文件名。
其他选项有:
-b 使用域进行分类时,忽略第一个空格。
-n 指定分类是域上的数字分类。
-t 域分隔符;用非空格或tab键分隔域。
-r 对分类次序或比较求逆。
+n n为域号。使用此域号开始分类。
n n为域号。在分类比较时忽略此域,一般与+n一起使用。
post1 传递到m,n。m为域号,n为开始分类字符数;例如4,6意即以第5域分类,从第7个字符开始。

最基本的sort方式为sort filename,按第一域进行分类(分类键0)。实际上读文件时sort操作将行中各域进行比较,这里返回基于第一域sort的结果:
sort -t: /etc/passwd > passwd.bak
如果要逆向sort结果,使用- r选项。在通读大的注册文件时,使用逆向sort很方便。下面是按域0分类的逆向结果:
sort -t: -r /etc/passwd > passwd.bak
有时需要只按第2域(分类键1)分类。这里为重排报文中供应区代码,使用t 1,意义为按分类键1分类:
sort -t: +1 /etc/passwd > passwd.bak
如果是数值域,即为数值分类,可以使用- n选项:
sort -t: +2n /etc/passwd > passwd.bak
有时,原文件中有重复行,这时可以使用- u选项进行唯一性(不重复)分类以去除重复行:
sort -u /etc/passwd > passwd.bak
可以指定分类键次序。先以第4域,再以第1域分类,命令为-k4 -k1
sort -t: -k4 -k1 /etc/passwd > passwd.bak
sort还可以用于d f命令,以递减顺序打印使用列下面是按占用空间百分比,第4+1域)
df | sort -r +4

split用来将大文件分割成小文件。有时文件越来越大,传送这些文件时,首先将其分割可能更容易。使用vi或其他工具诸如sort时,如果文件对于工作缓冲区太大,也会存在一些问题。因此有时没有选择余地,必须将文件分割成小的碎片。
split命令一般格式:
split -output_file-size input-filename output-filename
这里output-file-size指的是文本文件被分割的行数。split查看文件时,output-file-size选项指定将文件按每个最多1000行分割。如果有个文件有2800行,那么将分割成3个文件,分别有1000、1000、800行。每个文件格式为x[aa]到x[zz],x为文件名首字母, [aa]、[zz]为文件名剩余部分顺序字符组合。

例子:
test> ll
total 81
-rw-rw-r-- 1 wangnc users 82029 Aug 24 16:28 myfile
test> wc -l myfile
2082 myfile
test> split myfile
test> ll
total 162
-rw-rw-r-- 1 wangnc users 82029 Aug 24 16:28 myfile
-rw-rw-r-- 1 wangnc users 39633 Aug 24 16:29 xaa
-rw-rw-r-- 1 wangnc users 40481 Aug 24 16:29 xab
-rw-rw-r-- 1 wangnc users 1915 Aug 24 16:29 xac
按每个文件2行分割,命令为:
mydir3> ls
myfile
mydir3> wc -l myfile
2 myfile
mydir3> vi myfile
mydir3>
mydir3> wc -l myfile
7 myfile
mydir3> split -2 myfile
mydir3> ll
total 5
-rw-rw-r-- 1 wangnc users 102 Aug 24 16:33 myfile
-rw-rw-r-- 1 wangnc users 29 Aug 24 16:33 xaa
-rw-rw-r-- 1 wangnc users 29 Aug 24 16:33 xab
-rw-rw-r-- 1 wangnc users 30 Aug 24 16:33 xac
-rw-rw-r-- 1 wangnc users 14 Aug 24 16:33 xad

用户可以使用shell脚本创建交互性的、专业性强的屏幕输出。要实现这一点,系统上需要一个彩色监视器和tput命令。tput使用文件/etc/terminfo或/etc/termcap,这样就可以在脚本中使用终端支持的大部分命令了。
在使用tput前,需要在脚本或命令行中使用tput命令初始化终端。
$ tput init
tput产生三种不同的输出:字符型、数字型和布尔型(真/假)。
下面是大部分常用字符串:
bel 警铃
blink 闪烁模式
bold 粗体
civis 隐藏光标
clear 清屏
cnorm 不隐藏光标
cup 移动光标到屏幕位置( x,y)
el 清除到行尾
ell 清除到行首
smso 启动突出模式
rmso 停止突出模式
smul 开始下划线模式
rmul 结束下划线模式
sc 保存当前光标位置
rc 恢复光标到最后保存位置
sgr0 正常屏幕
rev 逆转视图
以下是大部分常用数字输出:
cols 列数目
it tab设置宽度
lines 屏幕行数
在tput中只有两种布尔操作符:
chts 光标不可见
hs 具有状态行

tr用来从标准输入中通过替换或删除操作进行字符转换。tr主要用于删除文件中控制字符或进行字符转换。使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。
带有最常用选项的tr命令格式为:
tr -c -d -s ["string1_to_translate_from"] ["string2_to_translate_to"] input-file
这里:
-c 用字符串1中字符集的补集替换此字符集,要求字符集为ASCII。
-d 删除字符串1中所有输入字符。
-s 删除所有重复出现字符序列,只保留第一个;即将重复出现字符串压缩为一个字符串。
Input-file是转换文件名。虽然可以使用其他格式输入,但这种格式最常用。

例子:
wangnc> pg oops.txt
And the cowwwwws went homeeeeeeee
Or did theyyyy

如果要去除重复字母或将其压缩在一起,使用- s选项。因为都是字母,故使用[a-z]。输入文件重定向到tr命令。
wangnc> tr -s "[a-z]" < oops.txt
And the cows went home
Or did they

要删除空行,可将之剔出文件。使用-s来做这项工作。换行的八进制表示为/012,命令为:
tr -s "[/012]" < plane.txt

大小写转换:
wangnc> echo "May Day,May Day,Going Down.." | tr "[a-z]" "[A-Z]"
MAY DAY,MAY DAY,GOING DOWN..
wangnc> echo "May Day,May Day,Going Down.." | tr "[A-Z]" "[a-z]"
may day,may day,going down..

将文本文件从小写转换为大写并将结果存入一个新文件,格式为:
cat file-to-translate | tr "[a-z]" "[A-Z]" > new-file-name

命令tr -cs "[a-z][A-Z]" "[/012*]"将文件每行所有不包含在[a-z]或[A-Z](所有希腊字母)的字符串放在字符串1中并转换为一新行。-s选项表明压缩所有新行, -c表明保留所有字母不动。

tr的第一个功能就是转换控制字符,特别是从dos向UNIX下载文件时,忘记设置ftp关于回车换行转换的选项时更是如此。
如果需要删除文件中^M,并代之以换行。使用命令:
tr -s "[/015]" "/n" < input-file
或者用下述命令得同样结果:
tr -s "[/r]" "[/n]" < input-file
也可以用下述命令:
tr -s "/r" "/n" < input-file
另一个一般的Dos到UNIX转换是命令:
tr -s "[/015/032]" "[/012*]" < input-file
将删除所有^ M和^ Z,代之以换行。
要删除所有的tab键,代之以空格,使用命令:
tr -s "[/011]" "[/040*]" < input-file
替换passwd文件中所有冒号,代之以tab键,可以增加可读性:
tr -s "[:]" "[/011]" < /etc/passwd
或者用下述命令得同样结果。这里使用tab键的速记符:
tr -s "[:]" "[/t]" < /etc/passwd

uniq用来从一个文本文件中去除或禁止重复行。可以认为uniq有点像sort命令中唯一性选项。对,在某种程度上讲正是如此,但两者有一个重要区别。sort的唯一性选项去除所有重复行,而uniq命令并不这样做。重复行是什么?在uniq里意即持续不断重复出现的行,中间不夹杂任何其他文本.
命令一般格式:
uniq -u d c -f input-file output-file
其选项含义:
-u 只显示不重复行。
-d 只显示有重复数据行,每种重复行只显示其中一行
-c 打印每一重复行出现次数。
-f n为数字,前n个域被忽略。
一些系统不识别-f选项,这时替代使用-n。
wangnc> pg myfile.txt
May Day
May Day
May Day
Going Down
May Day
wangnc> uniq myfile.txt > myfile.txt.1
wangnc> pg myfile.txt.1
May Day
Going Down
May Day
wangnc> sort -u myfile.txt > myfile.txt.2
wangnc> pg myfile.txt.2
Going Down
May Day
wangnc>
使用-c选项显示行数,即每个重复行数目:
uniq -c myfile.txt
使用-d显示重复出现的不唯一行:
uniq -d myfile.txt
使用-n只测试一行一部分的唯一性。例如-5意即测试第5域后各域唯一性。域从1开始记数。
如果忽略第1域,只测试第2域唯一性,使用-n2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值