UNIX SHELL编程
索引:
- 文件名生成通配符
- 正则表达式通配符
- find命令
- shell输入和输出
- 命令执行顺序
- stty命令
- shell变量
- 环境变量
- 引用
- 条件测试
- 控制流结构
- shell函数
- 脚本参数
- tput创建屏幕输出
- 创建临时文件
- 发送信号
- trap信号捕获
- eval
- grep
- awk
- sed
- tr
- 合并与分割
该部分讲述的是shell编程方面的知识,以Bourne Shell为主,因为它是使用最广泛的,因而移植性最好,虽然功能不如现代许多其他版本的shell强大。
篇幅不大,只是一个简明手册,不具备系统性。
1.文件名生成通配符
在shell中,有两种类型的通配符:文件名生成通配符和正则表达式通配符。两者是不同的,注意区分。
字符*
星号*匹配文件名中的任何字符串。
字符?
?匹配文件名中的任何单个字符。
[…]和[!…]
使用[…]匹配方括号中的任何字符。可以使用一个横杠来连接两个字母或数字,表示一个范围。
使用[!…]表示非的意思。
2.正则表达式通配符
(1).基本元字符集
元字符 | 含义 |
---|---|
^ | 只匹配行首,在[]中表示否定 |
$ | 只匹配行尾 |
* | 一个单字符后紧跟*,匹配0个或多个此字符 |
[] | 匹配[]内字符,可以是一个单字符,也可以是字符序列,可以使用-表示范围 |
\ | 用来屏蔽一个元字符的特殊含义 |
. | 匹配任意单字符 |
pattern\{n\} | 用来匹配前面pattern出现次数,n为次数 |
pattern\{n, \} | 含义同上,但次数最少为n |
pattern\{n, m\} | 含义同上,但次数在n与m之间 |
(2).\屏蔽的特殊字符
$ . ‘ “ * [ ] ^ | \ + ?
(3).例子
^$ | 匹配空行 |
[A-Za-z] | 匹配所有字母 |
[A-Za-z]* | 匹配所有单词 |
[^A-Za-z] | 匹配任一非字母型字符 |
A\{2, \} | 匹配AAB、AAAB、… |
[0-9]\{2\}-[0-9]\{2\}-[0-9]\{4\} | 匹配dd-mm-yyyy |
3.find命令
(1).find命令的形式:
find pathname -optino [ -pirnt -exec -ok ]
pahtname:查找的目录路径;
-print:将匹配的文件输出到标准输出;
-exec:对匹配的文件执行给出的shell命令,命令形式为‘command {} \;’,注意空格;
-ok:与-exec类似,在执行前会让用户确认。
(2).-name
按照文件名查找文件。
例:
查找$HOME目录及子目录下所有.txt文件:
find ~ -name "*.txt" -print
查找当前目录及子目录下以一个大写字母开头的文件:
find . -name "[A-Z]*" -print
查找/etc及子目录下以host开头的文件:
find /etc -name "host*" -print
查找$HOME目录及子目录下文件:
find ~ -name "*" -print或find . -print
查找当前目录及子目录下以两个小写字母打头,后跟两个数字,最后是.txt后缀的文件:
find . -name "[a-z][a-z][0-9][0-9].txt" -print
(3).-perm
按照权限查找。
例:
查找当前目录及子目录下权限为755的文件:
find . -perm 755 -print
查找当前目录及子目录下所有用户都可读、写、执行的文件(使用八进制数字前要加-):
find . -perm -007 -print
(4).-prune
忽略某个目录,如果同时使用了-depth,则-prune被忽略。
例:
find /apps -name "/apps/bin" -prune -o -print
(5).-user和-nouser
-user:按照文件属主查找;
-nouser:查找文件属主帐户已经被删除的文件。
例:
查找属主为duan的文件:
find ~ -user duan -print
查找文件属主帐户已经被删除的文件
find /home -nouser -print
(6).-group和-nogroup
-group:按照文件所属的组查找;
-nogroup:查找属于不存在的组的文件。
例:
查找属于用户组informix的文件
find /apps -group informix -print
查找不存在组的文件:
find / -nogroup -print
(7).-mtime
按更改时间查找,减号-限定更改时间距今n日内的文件,加号+限定更改时间距今n日外的文件。
例:
查找更改时间在5日内的文件:
find . -mtime -5 -print
查找更改时间在3日前的文件:
find . -mtime +3 -print
(8).-newer
查找更改时间新的文件,可以使用!逻辑非。
例:
查找比haha.txt新的文件:
find . -newer haha.txt
查找比haha.txt新但比find.txt旧的文件:
find . -newer haha.txt ! -newer find.txt -print
(9).-type
按类型查找。类型有:
- b,块设备文件;
- d:目录;
- c:字符设备文件;
- p:管道文件;
- l:符号链接文件;
- f:普通文件。
例:
查找目录文件:
find /etc -type d -print
查找非目录文件:
find . ! -type d -print
查找符号联接文件:
find /etc -type l -print
(10).-size
按照文件大小查找。单位是块,也可以是字节(后跟c)。
例:
查找字节大于1M的文件:
find . -size +1000000c -print
查找字节为100的文件:
find . -size 100c -print
查找大小大于10块的文件:
find . -size +10 -print
查找字节小于10的文件:
find . -size -10c -print
(11).-depth
先匹配所有文件,再在子目录中查找。
例:
先匹配当前目录中所有.txt文件,再在子目录中找:
find . -name "*.txt" -depth -print
(12).-mount
只在当前文件系统中查找,不进入其他文件系统。
例:
find . -name "*.txt" -mount -print
(13).-cpio
使用cpio命令将文件备份到磁带上。
例:
find etc home apps -depth -print -cpio /dev/rmt0
(14).-exec和-ok
对匹配的文件执行某操作。
例:
find logs -type f -mtime +5 -exec rm {} \; find . -name "*.log" -mtime +5 -ok rm {} \; find /etc -name "passwd*" -exec grep "rounder" {} \;
(15).和xargs结合使用
find . -name "*.txt -print |xargx file find . -name "*.txt" -print | xagrs echo >/tmp/tmpfile find . -perm -7 -print |xargs chmod o-w find . -type f -print |xargs grep "device" find . -name \* -type f -print |xargs grep "DBO"
4.shell输入和输出
(1).echo命令
显示文本行或变量,缺省会自动换行。
特殊字符:
\c:不换行;
\f:进纸;
\t:跳格;
\n:换行。
有些系统使用echo的-n选项来控制不换行。
特殊字符使用\来转义,如双引号。
(2).read命令
read命令从标准输入读入一行信息,并将其赋给变量。如果只有一个变量,则整行内容都赋给此变量,若有多个变量,则把输入内容按空格分开分别赋给变量,多余的输入内容全部赋给最后一个变量。
read形式为:
read var1 var2 …
(3).cat命令
cat命令显示文件内容,使用选项-v可以显示控制字符。
如:
cat myfile cat -v myfile
(4).tee命令
tee命令把输出的一个副本送到标准输出,另一个副本拷贝到相应的文件中。
如:
who | tee who.out; who | tee -a who.out;-a表示追加到文件末尾。
(5).文件重定向
文件描述符0为标准输入,文件描述符1为标准输出,文件描述符2为标准错误。
常用重定向命令:
command >filename:把标准输出重定向到一个新文件中; command >>filename:把标准输出重定向到一个文件(附加); command 1>filename:把标准输出重定向到一个新文件中; command >filename 2>&1:把标准输出和标准出错重定向到一个文件中; command 2>filename:把标准错误重定向到一个新文件中; command 2>>filename:把标准错误重定向到一个文件(附加); command >>filename 2>&1:把标准输出和标准出错重定向到一个文件中(附加); command < file >file2:以file为标准输入,以file2为标准输出; command < filename:以filename为标准输入; command << delimiter:从标准输入读入,直到遇到delimiter分界符; command <&m:把文件描述符m作为标准输入; command >&m:把标准输出重定向到文件描述符m中; command <&-:关闭标准输入。
(6).exec命令
exec命令替换当前shell,它践踏了你当前的shell。
一个例外是exec对文件描述符操作时,它不覆盖当前shell。
使用exec操作文件描述符,例如:
exec 4<&0 0<stock.txt;
把描述符4重定向到标准输入,把标准输入重定向到stock.txt。
exec 0<&4;
把描述符0重定向到描述符4,即恢复标准输入。
5.命令执行顺序
(1).使用&&
一般形式为:
命令1&& 命令2
含义:&&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行。
如:
cp justice.doc justice.bak && echo "cp was OK"
(2).使用||
一般形式为:
命令1|| 命令2
含义:如果左边的命令(命令1)未执行成功,那么就执行||右边的命令(命令2)。
如:
cp wopper.txt oops.txt || echo "cp failed"
(3).使用()和{}组合命令
在当前shell执行一组命令,形式为:
(命令1;命令2;…)
在子shell中执行一组命令,形式为:
{命令1;命令2;…}
如:
comet month_end || (echo "hello" | mail dave; exit)
6.stty命令
stty用于设置终端特性。
(1).查询现有终端设置
stty -a
(2).设置tty选项
stty name character
如:
stty erase ^H
在vi中输入控制字符:先按ctrl-v,再按该控制字符。
(3).保存stty现有设置
stty -g
以可读形式保存stty现有设置,便于以后恢复。
如:
SAVETTY=`stty -g` ... stty $SAVETTY
7.shell变量
(1).设置变量
- Variable_name = value,设置实际值到变量中;
- Variable_name + value,如果设置了变量,则使用value值,但不改变量的值;
- Variable_name :? value,如果未设置变量,显示用户错误信息value;
- Variable_name ? value,如果未设置变量,显示系统错误信息;
- Variable_name := value,如果设置了变量,则使用它,如果未设置变量,设置其值;
- Variable_name :- value,同上,但取值并不设置到变量中。
如:
echo "The file is ${FILES:?}" echo "The file is ${FILES:?' sorry cannot locate the files'}" COLOUR=blue echo "The sky is ${COLOUR:-grey} today"
(2).显示变量
在变量名前加$,可以用{}将变量名括起来。如:
echo ${CREAT_PICTURE}
(3).清除变量
使用unset命令清除变量。
(4).显示所有本地shell变量
使用set命令。
(5).设置只读变量
variable_name=value readonly variable_name
(6).查看所有只读变量
使用readonly命令。
(7).位置变量参数
传给脚本的参数可以使用如下变量进行访问,只有前9个可以直接访问,使用shift可以改变此限制:
$0、$1、$2、…、$9
其中$0为脚本名字,$1到$9为第一到第九个参数。
(8).特定变量参数
$#:传递到脚本的参数个数;
$*:以一个单字符串显示所有向脚本传递的参数;
$$:脚本运行的当前进程ID号;
$!:后台运行的最后一个进程的进程ID号;
$@:与$#类似;
$-:显示shell使用的当前选项,与set命令相同;
$?:显示最后命令的退出状态,0表示没有错误,其他任何值表明有错误。
8.环境变量
(1).设置环境变量
variable_name=value; export variable_name\ 或\ variable_name=value\ export variable_name\
(2).查看所有环境变量
使用env命令。
(3).环境变量列表
CDPATH; EXINIT; HOME; IFS; LOGNAME; MAIL; MAILCHECK; MAILPATH; PATH; PS1; PS2; SHELL; TERMINFO; TERM; TZ; EDITOR; PWD; PAGER; MANPATH; LPDEST/PRINTER。
9.引用
shell引用类型有:””双引号;’’单引号;`反引号;\反斜线。
(1).双引号
双引号可引用除字符$、`、\外的任意字符或字符串,这几个特殊字符是美元符号、反引号和反斜线,对shell来说,它们有特殊意义。
(2).单引号
类似于双引号,但shell会忽略任何引用值。
(3).反引号
反引号用于设置系统命令的输出到变量,shell将反引号的内容作为一个系统命令,并执行其内容。
(4).反斜线
反斜线屏蔽下一个字符的特殊含义。
具有特殊含义的字符:& * + ^ $ ` “ | ?。
如:
echo $$ 显示当前进程ID号; echo \$$ 显示$$; expr 12 \* 12 计算12乘以12; echo “This is a copyright \251 sign” 显示八进制字符;
10.条件测试
(1).语法
使用test命令,形式如下:
test condition 或 [ condition ] (在括号和条件之间要有空格)
测试结果为0表示成功,其他为失败。
(2).逻辑操作符
-a 逻辑与,操作符两边都为真,结果为真,否则为假;
-o 逻辑或,操作符一边为真,结果为真,否则为假;
! 逻辑否,条件为假,结果为真。
(3).测试文件状态
-d 目录 -f 正规文件 -L 符号连接 -r 可读 -s 文件长度大于0、非空 -w 可写 -u 文件有suid位设置 -x 可执行
如:
test -w score.txt [ -d appbin ] [ -w b1.txt -a -w b2.txt ]
(4).字符串测试
字符串测试有5种格式:
test "string" test string_operator "string" test "string" string_operator "string" [ string_operator string ] [ string string_operator string ]
其中string_operator可为:
= 两个字符串相等;
!= 两个字符串不等;
-z 空串;
-n 非空串。
如:
[ -z $EDITOR ] [ $EDITOR = "vi" ] [ "$TAPE1" = "$TAPE2" ] [ "$TAPE1" != "$TAPE2" ]
(5).数值测试
格式如下:
"number" number_operator "number" or [ "number" number_operator "number" ]
其中numbe_operator可为:
-eq 数值相等;
-ne 数值不等;
-gt 第一个数大于第二个数;
-lt 第一个数小于第二个数;
-le 第一个数小于等于第二个数;
-ge 第一个数大于等于第二个数。
如:
[ "$NUMBER" -eq "300" ] [ "$NUMBER" -gt "300" ] [ "$NUMBER" -gt "$SOURE_COUNT" ] [ "99" -le "993" ]
(6).expr用法
expr命令一般用于数值计算,但也可用于字符串。格式如下:
expr argument operator argument
如:
expr 10 + 10 expr 30 / 3 expr 30 / 3 / 2 expr 30 \* 3 乘法要用反斜线 LOOP=0 LOOP=`expr $LOOP + 1`
可以用expr测试一个数,如果试图计算非整数,将返回错误:
$VALUE=hello expr $VALUE + 10 >/dev/null 2>&1 echo $? (失败)
expr还能比较字符串和进行模式匹配。expr的返回值成功为1,与系统的最后退出命令结果刚好相反,不要混淆。
11.控制流结构
(1).退出状态
退出shell使用如下命令:
exit n
其中n为退出状态,0表示成功,1表示失败。
(2).if then else语句
格式为:
if condition1 then (if和then不在同一行) .... elif condition2 then .... else .... fi 或: if condition; then (if和then在一行时要用分号) .... fi
例如:
if [ “10” -le “12” ] then … fi if grep david ha.txt >/dev/null 2>&1 then … fi
(3).交互模式
测试脚本是交互模式还是非交互模式,使用test的-t选项,若测试成功,则为交互方式。如:
if [ -t ]; then echo “we are interactive with a terminal” fi
(4).空语句
if语句各部分都不能为空,可以使用空命令解决这个问题。
空语句形式为一个冒号:。
if [ -z $DIR ] then echo “DIR is empty” else : #do nothing fi
(5).case语句
case语句格式:
case 值 in 模式1) 命令1 … ;; 模式2) 命令2 … ;; esac
模式:
模式可以使用元字符:* ? [ ... ]。
模式中可以使用“|”作为或命令。
示例:
case $TERMINAL in vt100|vt102) TERM=vt100 ;; vt200) TERM=vt200 ;; *) echo “not valid” exit 1 ;; esac
(6).for循环
for语句格式:
for 变量名 in 列表 do 命令1 命令2 … done
列表:
省略in列表时,for接收命令行位置参数作为参数,等同于:
for param in “$@” 或 for param in “$*”
示例:
for loop in 1 2 3 4 5 for loop in “orange red blue grey” for loop in `ls`
(7).until循环
until循环执行一系列命令直至条件为真停止。
until格式:
until 条件 命令1 … done
条件测试发生在循环末尾,因此循环至少执行一次。
(8).while循环
while循环格式:
while 命令 do 命令1 命令2 .. done
永真循环:
while : do … done
(9).使用break和continue
break允许跳出循环或case语句。如果在一个嵌套循环里,可以指定跳出的循环个数。如在两层循环里,用break 2刚好跳出整个循环。
continue跳过当前循环步,继续下一循环。
12.shell函数
(1).函数定义格式
function 函数名() { 命令1 … }
(2).函数参数
函数里使用参数就象在一般脚本中使用特殊变量$1、$2等一样。
(3).函数返回
函数结束可以用return返回函数执行结果:
return 从函数返回,用最后状态命令决定返回值; return 0 无错误返回; return 1 有错误返回。
(4).函数返回值测试
在脚本调用函数语句的后面使用最后状态命令测试函数的返回值。如:
check_is_directory $FILENAME if [ “$?” = “0” ] then … fi
更好的方法是在if中测试。如:
if check_is_directory $FILENAME then … fi
(5).函数文件
文件的首行为#!/bin/sh。
装入函数文件格式:
. /pathname/filename
在shell中装入后,可以用set命令查看,用unset删除。
在脚本中装入后,可以在脚本中使用定义的函数。
13.脚本参数
(1).处理方式
脚本处理参数有三种方式:
- 使用特定变量$1、$2、...、$9,$#统计参数个数。此法的缺点是只能处理9个参数;
- 使用shift;
- 使用getopts。
(2).shift
shift的功能是每次将参数位置向左偏移一位,通过循环可以处理所有的参数。
如:
while [ $# -ne 0 ] do echo $1 shift done
(3).获得命令行输入的最后一个参数
有两种方法:
- 使用命令:eval echo \$$#;
- 使用命令:shift `expr $#-2`。
(4).getopts
使用getopts可以处理复杂的命令行参数。
getopts的一般格式为:
getopts option_string variable
option_string:
所有选项字母组合成option_string;
若选项有取值,则在字母后加一个冒号,取值时,存放在OPTARG变量中;
使用自定义的错误信息,在option_string前加冒号,在处理语句(如case)中使用?创建一可用语句捕获错误。
如:
命令行为:-[a v] -[c value] file
while getopts :avc: OPTION do case $OPTION in a) ALL=true echo "ALL is $ALL" ;; v) VERBOSE=true echo "VERBOSE is $VERBOSE" ;; c) COPIES=$OPTARG echo "COPIES is $COPIES" ;; \?) echo "`basename $0` -[a v] -[c value] file" >&2 ;; esac done
14.tput创建屏幕输出
(1).初始化终端
使用tput,需初始化终端,方法:
tput init
(2).输出类型
tput产生三种输出:字符型、数字型和布尔型(真/假)。
(3).字符串输出
bel | 警铃 |
blink | 闪烁模式 |
bold | 粗体 |
civis | 隐藏光标 |
clear | 清屏 |
cnorm | 不隐藏光标 |
cup | 移动光标到屏幕位置(x,y) |
el | 清除到行尾 |
ell | 清除到行首 |
smso | 启动突出模式 |
rmso | 停止突出模式 |
smul | 开始下划线模式 |
rmul | 结束下划线模式 |
sc | 保存当前光标位置 |
rc | 恢复光标到最后保存位置 |
sgr0 | 正常屏幕 |
rev | 逆转视图 |
(4).数字输出
cols | 列数目 |
it | tab设置宽度 |
lines | 屏幕行数 |
(5).布尔输出
chts | 光标不可见 |
hs | 具有状态行 |
(6).使用布尔输出
STATUS_LINE=`tput hs` if $STATUS_LINE ; then echo "has a status line" … fi
(7).使用字符型输出
BOLD=`tput bold` REV=`tput rev` NORMAL=`tput sgr0` CURSOR_OFF=`tput civis` CURSOR_ON=`tput cnorm` tput init echo $CURSOR_OFF echo "${BOLD} WELCOME TO THE PIZZA ${NORMAL}" echo "\n${REV}WE ARE OPEN 7 DAYS A WEEKS${NORMAL}" echo $CURSOR_ON
(8).光标位置
用tput将光标放在屏幕任意位置,方法如下:
tput cup r c
(9).在屏幕中心位置显示文本
centertxt() { _ROW=$1 _STR=$2 LEN=`echo $_STR | wc -c` echo $LEN COLS=`tput cols` echo $COLS NEW_COL=`expr \( "$COLS" - "$LEN" \) / 2` xy 10 $NEW_COL $STR }
(10).在脚本中使用功能键
使用cat命令可获得任意特殊键控制序列(如F1,箭头等),方法:
cat -v回车,按任意键,回车,即获得功能键。
在脚本中使用这些控制键时要注意,不同系统取值可能不同。
uparrowkey=' [A' downarrowkey=' [B' echo -n "Press a control key then hit return" read KEY case $KEY in $uparrowkey) echo "Up Arrow" ;; $downarrowkey) echo "Down Arrow" ;; esac
(11).使用颜色
颜色对应的数字:(不是所有颜色都适合所有系统)
前景色:
数字 | 颜色 |
---|---|
30 | 黑色 |
31 | 红色 |
32 | 绿色 |
33 | 黄(棕)色 |
34 | 蓝色 |
35 | 紫色 |
36 | 青色 |
37 | 白(灰)色 |
背景色:
数字 | 颜色 |
---|---|
40 | 黑色 |
41 | 红色 |
42 | 绿色 |
43 | 黄(棕)色 |
44 | 蓝色 |
45 | 紫色 |
46 | 青色 |
47 | 白(灰)色 |
显示颜色格式为:
<Escape> [ backgroud_number ; foreground_number m
在脚本中使用echo语句产生颜色:
colour() { case $1 in black_green) echo "\033[40;32m" ;; black_yellow) echo "\033[40;33m" ;; black_white) echo "\033[40;37m" ;; black_cyan) echo "\033[40;36m" ;; black_red) echo "\033[40;31m" ;; esac }
15.创建临时文件
临时文件和日志文件可以使用date命令或$$(当前进程ID)生成名字唯一的文件名。
16.发送信号
常用信号:
号码 | 名称 | 说明 |
---|---|---|
1 | SIGHUP | 挂起或父进程被杀死 |
2 | SIGINT | 来自键盘的中断信号,如ctrl-c |
3 | SIGQUIT | 从键盘退出 |
9 | SIGKILL | 无条件终止 |
11 | SIGSEGV | 段(内存)冲突 |
15 | SIGTERM | 软件终止(缺省杀进程信号) |
发送信号使用kill命令:
kill [ -signal no | signal name ] process_id
17.trap信号捕获
对信号有三种处理方式:系统默认;忽略;捕获。
(1).捕获信号
trap “do_something” signal no(s)
如:
trap “my_exit” 2 3 (my_exit为一个函数或命令)
(2).忽略信号
trap “” signal no(s)
如:
trap “” 1 2 3 15
(3).恢复系统默认状态
trap signal no(s)
如:
trap 2 3
18.eval
eval首先扫描命令行进行所有的置换,然后再执行命令。该命令适用于那些一次扫描无法实现其功能的变量。
如:
显示文件testfile的内容:
MYFILE=”cat testfile” eval $MYFILE
19.grep
(1).一般格式
grep [选项] 基本正则表达式 [文件]
这里正则表达式可以为字符串。在命令中输入字符串参数时,最好用双引号括起来。在调用模式匹配时,应使用单引号。
(2).grep选项
-c,只输出匹配行的计数
-i,不区分大小写(只适用于但字符)
-h,查询多文件时不显示文件名
-l,查询多文件时只输出包含匹配字符的文件名
-n,显示匹配行及行号
-s,不显示不存在或无匹配文本的错误信息
-v,显示不包含匹配文本的所有行
(3).国际字符匹配模式的类名形式
类 | 等价的正则表达式 |
---|---|
[[:upper:]] | [A-Z] |
[[:lower:]] | [a-z] |
[[:digit:]] | [0-9] |
[[:alnum:]] | [0-9a-zA-Z] |
[[:space:]] | 空格或TAB键 |
[[:alpha:]] | [a-zA-Z] |
(4).例子
grep -c "sort" *.dat
输出匹配sort的行数。
grep '^[^48]' data.f
匹配不以49开头的行。
grep '6\{2,6\}' file.h
匹配6出现2-6次的行。
grep '5[[:upper:]][[:upper:]]' data.f
匹配5后跟两个大写字母的行。
20.awk
(1).命令格式
有三种方式:
命令行方式:
awk [ -F 域分隔符 ] ‘commands’ input_file(s)
域分隔符不指定时缺省为空格,commands是awk命令语句。
- awk脚本方式。
awk命令文本方式:
awk -f awk_script_file input_file(s)
(2).awk语句的构成
awk语句都由模式和动作组成。模式决定何时进行操作,动作是操作的具体内容。
模式可以是任何条件语句或复合语句或正则表达式。有两个特殊模式:BEGIN和END。BEGIN在任何文本浏览动作之前,END使用在完成文本浏览之后。
实际动作在{}中指定,简单如打印,复杂的如控制和循环等。
(3).域和记录
awk执行时,其浏览域用$1、$2、…、$n标识,多个域之间用逗号分隔,如$1,$3。
$0标识整个记录(整行)。
(4).awk中的正则表达式
除了基本的元字符外,awk中还可以使用如下两个字符:
+,匹配一个或多个字符;
?,匹配模式出现频率。
(5).awk条件操作符
操作符 | 描述 | 操作符 | 描述 |
---|---|---|---|
< | 小于 | >= | 大于等于 |
<= | 小于等于 | ~ | 匹配正则表达式 |
== | 等于 | !~ | 不匹配正则表达式 |
!= | 不等于 |
要匹配一个正则表达式,可以使用~后紧跟/正则表达式/,也可使用if语句,if后面的条件用()括起来。
如:
awk '{if ($4 ~ /Brown/) print $0}' grade.txt awk '$4 ~ /Brown/ {print $0}' grade.txt
(6).复合条件操作符
&&:语句两边必须同时匹配为真。
||:语句两边同时或其中一边为真。
!:求逆。
如:
awk '{if ($1 == "P.Bunny" && $4 == "Yellow") print $0}' grade.txt awk '{if ($4 == "Yellow" || $4 ~ /Brown/) print $0}' grade.txt
(7).awk内置变量
ARGC | 命令行参数个数 |
ARGV | 命令行参数排列 |
ENVIRON | 支持队列中系统环境变量的使用 |
FILENAME | Awk正在浏览的文件名 |
FNR | 浏览文件的记录数 |
FS | 设置输入域分隔符,等价于命令行-F选项 |
NF | 浏览记录的域个数 |
NR | 已读的记录数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
RS | 控制记录分隔符 |
访问命令行参数的方法:ARGV[n]。
访问系统环境变量:ENVIRON[ “EDITOR” ] = “vi”。
FNR表示awk目前操作的记录数,其值小于等于NR。
NF表示记录域个数,在记录被读之后设置。
OFS允许指定输出域分隔符,缺省为空格。
ORS允许指定输出记录分隔符,缺省为新行(\n)。
RS为记录分隔符,缺省为新行(\n)。
例:
显示记录个数:
awk 'END {print NR}' grade.txt
文件非空时才操作:
awk '{if (NR > 0 && $4 ~ /Bronw/) print $0}' grade.txt
显示路径中的文件名:
echo “/usr/sybase/etc/rc.file” |awk -F/ '{print $NF}'
(8).awk其他操作符
= += -= *= /= %= ^= | 赋值操作符 |
? | 条件表达操作符 |
+ - * / % ^ | 算术操作符 |
++ -- | 前缀和后缀 |
在awk中可以设置变量。如:
awk '{name=$1; belts=$4; \ if (belts ~ /Yellow/) print name" is belt "belts}' grade.txt
(9).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 |
sprintf(fmt,exp) | 返回经fmt格式化后的exp |
sub(r,s) | 在$0中用最左边最长的子串s替代r |
substr(s,p) | 返回字符串s中从p开始的后缀部分 |
substr(s,p,n) | 返回字符串s中从p开始长度为n的后缀部分 |
使用举例:
awk 'gsub(/4842/,4899) {print $0}' grade.txt awk 'BEGIN {print index("Bunny","ny")}' grade.txt awk '$1 == "J.Troli" {print length($1)" "$1}' grade.txt awk 'BEGIN {print length("A good man")}' awk 'BEGIN {print match("ABCD", /d/) }' awk 'BEGIN { print split("123#456#678", myarray, "#"); \ print myarray[1]; print myarray[2]; print myarray[3])}' awk "$1 == "J.Troli" {sub(/26/, "29", $0); print $0}' grade.txt awk '$1 == "L.Tanskey" {print substr($1, 1, 5)}' grade.txt awk '{print substr($1, 3)}' grade.txt
(10).字符串屏蔽序列
\b 退格键
\f 走纸换页
\n 新行
\r 回车键
\t tab键
\ddd 八进制值
\c 任意其他特殊字符,如\\为反斜线
(11).awk输出函数printf
基本语法:
printf( [格式控制项],参数)格式控制类似与c语言中的printf函数。
例如:
awk 'BEGIN { printf "%f\n", 999}' awk 'BEGIN {print "Name\t\tS.Number"} \ {printf "%-15s %s\n", $1, $3 }'(12).在命令行向awk传值
格式:
awk 命令变量=输入值。如:
df -k |awk '($4 ~ /^[0-9]/) \ { if ($4 < TRIGGER) print $6"\t"$4}' TRIGGER=5600 who |awk '{ if ($1 == user) print $1"connected to "$2}' \ user=$LOGNAME(13).awk数组
数组使用前不用定义,一般使用循环来访问数组。格式:
for ( element in array ) print array[element]
21.sed
(1).命令格式
调用sed有三种格式:
命令行格式:
sed [选项] sed命令 输入文件
使用sed脚本文件:
sed [选项] -f sed脚本文件 输入文件
可执行sed脚本:
sed脚本 [选项] 输入文件
当没有输入文件时,sed从标准输入中接收输入。sed不会对原始输入文件做修改。
sed命令要用单引号括起来。
sed选项:
n:不打印,sed不写编辑行到标准输出,缺省为打印所有行(编辑和未编辑)。
c:无用。
f:调用脚本文件。
(2).sed定位文本的方式
x | x为一行号,如1 |
x,y | 表示行号范围从x到y,如2,5 |
/pattern/ | 查询包含模式的行 |
/pattern/pattern/ | 查询包含两个模式的行 |
pattern/,x | 在给定行号上查询包含模式的行 |
x,/pattern/ | 通过行号和模式查询匹配行 |
x,y! | 查询不包含指定行号x和y的行 |
sed模式匹配使用正则表达式。
(3).基本sed编辑命令
p | 打印匹配行 |
= | 显示文件行号 |
a\ | 在定位行号后附加新文本信息 |
i\ | 在定位行号后插入新文本信息 |
d | 删除定位行 |
c\ | 用新文本替换定位文本 |
s | 使用替换模式替换相应模式 |
r | 从另一个文件中读文本 |
w | 写文本到一个文件 |
q | 第一个模式匹配完成后退出或立即退出 |
l | 显示与八进制ASCII码等价的控制字符 |
{} | 在定位行执行的命令组 |
n | 从另一个文件中读文本下一行,并附加在下一行 |
g | 将模式2粘贴到/pattern n/ |
y | 传送字符 |
n | 延续到下一输入行,允许跨行的模式匹配 |
例如:
显示文本1到3行:
sed -n '1,3p' quote.txt
显示匹配的行:
sed -n '/Neave/p' quote.txt
在第四行查询模式:
sed -n '4,/The/p' quote.txt
匹配元字符(使用反斜线屏蔽含义):
sed -n '/\$/p' quote.txt
显示整个文件:
sed -n '1,$p' quote.txt
打印模式匹配的行号:
sed -n '/music/=' quote.txt
删除匹配的文本行:
sed '/Neave/d' quote.txt
写入文件/从文件读:
sed '/Neave/w dht' quote.txt sed '/company/r sedex.txt' quote.txt
匹配后退出:
sed '/.a.*/q' quote.txt
显示文件中控制字符:
sed -n '1,$l' func.txt
(4).附加文本
附加文本的操作格式(附加文本中的\表示换行,最后一行不加\,表示结束):
[address]a\ text\ text\ text
插入文本、修改文本与此类似。
(5).替换文本
格式:
[address[,address]] s/pattern-to_find/replace_pattern/[g p w n]
替换选项:
g,缺省替换第一次出现,使用g替换所有出现。
p,打印。
w 文件名,将输出结果写到文件。
如:
sed -n 's/night/NIGHT/p' quote.txt
附加或修改原匹配模式,可以使用(&)命令,&保存发现模式。
将nurse改为”Hello” nurse:
sed -n 's/nurse/"Hello" &/p' quote.txt
22.tr
(暂缺)
23.合并与分割
(1).sort
(2).uniq
(3).join
(4).cut
(5).paste
(6).split