为使shell编程更有效,系统提供了一些shell变量。变量可以定制用户本身的工作环境。使用变量可以保存有用信息,使系统获知用户相关设置;变量也用于保存暂时信息。
有两种变量:本地变量 和 环境变量。
)本地变量
本地变量在用户现在的Shell生命期的脚本中使用。
要设置一本地变量,格式为: variable-name = value or ${variable-name=value}
定义变量:可以使用export 来定义导出一变量,export variable-name=”variable-value”
显示变量:使用echo命令可以显示单个变量值,echo $variable-name
清除变量:使用unset命令清除变量,unset variable-name
显示所有变量:使用set 显示所有本地定义的shell变量;使用env显示所有shell变量。
例子:
$ export MYNAME=”hongdy”
$ echo $MYNAME
hongdy
$ env
$ set
$ unset MYNAME
(2)环境变量
环境变量用于所有用户进程(子进程),登录进程为父进程。Shell中执行的用户进程均为子进程 。最好在.profile中定义,系统在/etc/profile文件中已经设置了一些环境变量。
设置环境变量:使用export导出环境变量,export VARIABLE-NAME
显示环境变量:使用echo命令可以显示环境变量,echo $(VARIABLE-NAME)
清除环境变量:使用unset命令清除环境变量,unset VARIABLE-NAME
显示所有环境变量:env显示所有环境变量
下面显示的是Shell的一些基本环境变量
变量 |
说明 |
SHELL |
变量保存缺省shell ,在/etc/passwd中设置 |
TERM |
保存终端类型 |
TZ |
时区变量保存时区值 |
HOME |
用于保存注册目录的完全路径名 |
UID |
当前用户的标识符,取值是由数字构成的字符串 |
PWD |
当前工作目录的绝对路径名,该变量的取值随cd命令的使用而变化 |
PS1 |
主提示符,在root用户缺省的主提示符是“#”,普通用户缺省是“$” |
PS2 |
在shell接收用户输入命令的过程中,如果用户在输入行的末尾输入“\”然后回车,或者当用户按回车键时shell判断出用户输入的命令没有结束时,显示这个辅助提示符,提示用户继续输入命令的其余部分,缺省的辅助提示符是“>” |
)位置变量
位置参数是一种在调用shell程序的命令行中按照各自的位置决定的变量,是在程序名之后输入的参数。位置参数之间用空格分隔,shell取第一个位置参数替换程序文件中的$1,第二个替换$2,依次类推。$0是一个特殊的变量,它的内容是当前这个shell程序的文件名即脚本名。
每个访问参数前要加&符号,第一个参数为0,表示预留保存实际脚本名字。
比如向脚本传送 I love you
$0 &1 &2 &3
脚本名字 I love you
例子:
$ vi findfile
#!/bin/sh
find / -name $1 -print
$ chmod a+x findfile
$ ./findfile /etc/passwd
特定变量参数
参数 |
含义 |
$# |
传递到脚本的参数个数 |
$* |
所有位置参数的内容 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一进程的进程ID号 |
$0 |
当前执行的进程名 |
$@ |
与$#相同,但在使用时要加引号 |
$? |
命令执行后返回的状态 一般为 0 |
输入和输出
在shell脚本中,可以用几种不同的方式读入数据:可以使用标准输入—缺省为键盘,或者指定一个文件作为输入。对于输出也是一样:如果不指定某个文件作为输出,标准输出总是和终端屏幕相关联。
)echo
使用echo命令可以显示文本或者把字符串输入到文件。
$ echo string
\c 不换行;\t 跳格;\n 换行;
-n选项禁止echo命令输出后换行,-e使转义符生效。
)read
Read语句从键盘或文件的某一行文本中读入信息,并将其付给一个变量,空格作为分隔符。
)cat
cat是一个简单而通用的命令,可以用它来显示文件内容,创建文件,还可以用它来显示控制字符。
例子:
$ export NAME=hongdy
$ echo $NAME
hongdy
在使用cat命令时要注意,它不会在文件分页符处停下来;它会一下显示完整个文件。如果希望每次显示一页,可以使用more命令或把cat命令的输出通过管道传递到另外一个具有分页功能的命令中,比如:$ cat myfile | more
如果希望创建一个新文件,并向其中输入内容,cat命令把标准输出重定向到该文件中,标准输入是键盘,输入完毕按ctrl+D结束输入。
cat > myfile
hongdy // 输入的内容,然后回车
ctrl+d // 结束输入返回
(4)pipe
可以通过管道把一个命令的输出传递给另一个命令作为输入,管道用竖杠 | 表示。
比如:$ ls | grep *.txt 在ls结果中搜索txt文件
)tee
tee命令作用可以用字母T来形象地表示。它把输出的一个副本输送到标准输出,另一个副本拷贝到相应的文件中。
tee命令的一般形式:tee –a files -a 表示追加到文件末尾
比如:$ ls | tee result 将ls结果显示到标准输出,同时拷贝到文件中。
)重定向
标准输入是文件描述符0;标准输出是文件描述符1;标准错误是文件描述符2
$ command 1>filename // 把标准输出重定向到一个文件中
$ command > filename 2>&1 // 把标准输入和标准错误一起重定向到一个文件中
$ command < filename // 命令以filename文件作为标准输入
例子:
$ grep “hello” * > result 2>&1
gerp 的结果将标准错误重定向到标准输出。
使某些进程在后台运行,也就是说不在终端屏幕上运行。后台执行命令有以下四种:
命令 |
含义 |
cron |
系统调度进程,使用它在每天的非高峰负荷时间段运行作业,或在一周或一月中的不同时段运行 |
at |
at命令,在一个特定的时间运行一些特殊的作业,或在非负荷高峰时间段或高峰负荷时间段运行 |
& |
使用它在后台运行一个占用时间不长的进程 |
nohup |
使用它在后台运行一个命令,即使在用户退出时也不受影响 |
)cron
cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业。由于Cron 是Linux的内置服务,但它不自动启动,可以用以下的方法启动、关闭这个服务:
# /sbin/service crond start //启动服务
# /sbin/service crond stop //关闭服务
# /sbin/service crond restart //重启服务
# /sbin/service crond reload //重新载入配置
也可以将这个服务在系统启动的时候自动启动。
比如:在/etc/rc.d/rc.local这个脚本的末尾加上 /sbin/service crond start
crontab命令
crontab命令的一般形式为:crontab [-u user] -e -l –r
-u 用户名;-e 编辑crontab文件;-l 列出crontab文件中的内容;-r 删除crontab文件。
cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:
# crontab -u // 设定某个用户的cron服务,一般root用户在执行此命令的时候需要此参数
# crontab -l // 列出某个用户cron服务的详细内容
# crontab -r // 删除某个用户的cron服务
# crontab -e // 编辑某个用户的cron服务
例子:
root查看自己的cron设置:# crontab -u root -l
root删除hongdy用户的cron设置: # crontab -u hongdy -r
在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root –e ,进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt
这个格式的前一部分是对时间的设定,后面一部分是要执行的命令,如果要执行的命令太多,可以把这些命令写到一个脚本文件,然后在这里直接调用这个脚本文件,调用的时候写出命令的完整路径。
时间的设定我们有一定的约定,前面五个*号代表五个数字,数字的取值范围和含义如下:
分钟(0-59);小時(0-23);日期(1-31);月份(1-12);星期(0-6)//0代表星期天
除了数字还有几个特殊的符号就是"*"、"/"和"-"、",",*代表所有的取值范围内的数字,/代表每的意思,"*/5"表示每5个单位,"-"代表从某个数字到某个数字, ","分开几个离散的数字。
:
(1) 每天早上6点
0 6 * * * echo "Good morning." >> /tmp/test.txt
(2) 每两个小时
0 */2 * * * echo "Have a rest" >> /tmp/test1.txt
(3) 晚上11点到早上8点之间每两个小时,早上八点
0 23-7/2,8 * * * echo "Have a good dream" >> /tmp/test3.txt
(4) 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
0 11 4 * 1-3 echo "Have a rest" >> /tmp/test4.txt
(5) 1月1日早上4点
0 4 1 1 * echo "Have a rest" >> /tmp/test5.txt
每次编辑完某个用户的cron设置后,cron自动在/var/spool/cron下生成一个与此用户同名的文件,此用户的cron信息都记录在这个文件中,这个文件是不可以直接编辑的,只可以用crontab -e 来编辑。cron启动后每过一份钟读一次这个文件,检查是否要执行里面的命令。因此此文件修改后不需要重新启动cron服务。
)at命令
at命令允许用户向cron守护进程提交作业,使其在稍后的时间运行。这里稍后的时间可能是指10 min以后,也可能是指几天以后。如果你希望在一个月或更长的时间以后运行,最好还是使用crontab文件。一旦一个作业被提交,a t命令将会保留所有当前的环境变量。
At命令
at命令的基本形式为: at [-f script] [-m -l -r] [time] [date]
其中:
-f script 是所要提交的脚本或命令。
-m 作业完成后给用户发邮件。
-l 列出当前所有等待运行的作业。
-r 清除作业。为了清除某个作业,还要提供相应的作业标识(ID)。
time at命令的时间格式非常灵活;可以是H、HH . HHMM、HH:MM或H:M,其中H和M分别是小时和分钟。还可以使用a . m .或p . m .。
date 日期格式可以是月份数或日期数,而且at命令还能够识别诸如today之类的词。
使用at命令提交作业有几种不同的形式:可以通过命令行方式,也可以使用a t命令提示符。
如果你想提交若干行的命令,可以在at命令后面跟上日期/时间并回车。然后就进入了at命令提示符,这时只需逐条输入相应的命令,然后按 退出。
例子:
提交作业
# at 10:50
at> find / -name “passwd” –print
at>
其中就是。
清除作业
$atrm [job no]或 at -r [job no]
要清除某个作业,首先要执行at -l命令,以获取相应的作业标识,然后对该作业标识使用at -r 命令,清除该作业。
)&命令
当在前台运行某个作业时,终端被该作业占据;而在后台运行作业时,它不会占据终端。
可以使用&命令把作业放到后台执行。
)nohup命令
如果正在运行一个进程,而且觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令。该命令可以在你退出帐户之后继续运行相应的进程。Nohup就是不挂起的意思( no hang up)。
nohup命令的一般形式为:nohup command &
使用shell时,从一个文件中抽取多于一个字符串将会很麻烦。例如:在一个文本中抽取一个词,它的头两个字符是大写的,后面紧跟四个数字。如果不使用某种正则表达式,在shell中将不能实现这个操作。
基本元字符集及其含义
元字符 |
含义 |
^ |
只匹配行首 |
$ |
只匹配行尾 |
* |
一个单字符后紧跟*,匹配0个或多个此单字符 |
[] |
匹配[]内字符。可以是一个单字符,也可以是字符序列。可以使用-表示[]内字符序列范围,如用[1-5 ]代替[12345] |
\ |
用来屏蔽一个元字符的特殊含义。因为shell中一些元字符有特殊含义。\可以使其失去应有意义匹配任意单字符 |
pattern\{n\} |
只用来匹配前面pattern出现次数,n为次数 |
pattern\{n,\}m |
含义同上,但次数最少为n |
pattern\{n,m\} |
含义同上,但pattern出现次数在n与m之间 |
句点“.”可以匹配任意单字符。例如:如果要匹配一个字符串,以beg开头,中间夹一个任意字符,那么可以表示为beg.n,“.”可以匹配字符串头,也可以是中间任意字符。
匹配字符串或字符序列
^只允许在一行的开始匹配字符或单词。
匹配字符串或字符
可以说$与^正相反,它在行尾匹配字符串或字符, $符号放在匹配单词后。假定要匹配以单词txt结尾的所有行txt$
匹配字符串中的单字符或其重复序列
使用此特殊字符匹配任意字符或字符串的重复多次表达式。例如:compu*t将匹配字符u一次或多次。
屏蔽一个特殊字符的含义
有时需要查找一些字符或字符串,而它们包含了系统指定为特殊字符的一个字符。
什么是特殊字符?一般意义上讲,下列字符可以认为是特殊字符: $ . ‘ “” [ ] ^ | () \ + ?
假定要匹配包含字符“.”的各行而“.”代表匹配任意单字符的特殊字符,因此需要屏蔽其含义。操作如下:\ . 不认为反斜杠后面的字符是特殊字符,而是一个普通字符即句点。
如果要在正则表达式中匹配以*.txt结尾的所有文件,可做如下操作: \*\.txt 即可屏蔽字符*的特定含义。
匹配模式结果出现的次数
使用*可匹配所有匹配结果任意次,但如果只要指定次数,就应使用\ { \ },此模式有三种形式,即:
pattern\{n\} 匹配模式出现n次。
pattern\{n,\} 匹配模式出现最少n次。
pattern\{n,m} 匹配模式出现n到m次之间,n , m为0 - 2 5 5中任意整数。
1.5 grep
全局正则表达式版本grep允许对文本文件进行模式查找,可以和正则表达式一起使用。
grep一般格式:grep [选项] 基本正则表达式 [文件]
基本正则表达式可为字符串。在grep命令中输入字符串参数时,最好将其用双引号括起来。有两个原因,一是以防被误解为shell命令,二是可以用来查找多个单词组成的字符串。
常用的grep选项:
选项 |
含义 |
-c |
只输出匹配行的计数 |
-i |
不区分大小写 |
-h |
查询多文件时不显示文件名 |
-l |
查询多文件时只输出包含匹配字符的文件名 |
-n |
显示匹配行及行号 |
-s |
不显示不存在或无匹配文本的错误信息 |
-v |
显示不包含匹配文本的所有行 |
-R |
递归进入子目录 |
缺省情况下, grep是大小写敏感的,如要查询大小写不敏感字符串,必须使用-i开关。
精确匹配:每个匹配模式中抽取字符串后有一个键;使用grep抽取精确匹配的一种更有效方式是在抽取字符串后加\>。
使用正则表达式使模式匹配加入一些规则,因此可以在抽取信息中加入更多选择。使用正则表达式时最好用单引号括起来,这样可以防止grep中使用的专有模式与一些shell命令的特殊方式相混淆。
例子:
# grep –R –n –s “hongdy” /etc
查找/etc目录下所有包含hongdy的文件。-R表示递归查找etc下的所有目录;-n 表示显示匹配行及行号;-s 表示不显示不存在或无匹配文件的错误信息。
1.6 tr
tr用来从标准输入中通过替换或删除操作进行字符转换,主要用于删除文件中控制字符或进行字符转换。
使用tr时要转换两个字符串:字符串1用于查询,字符串2用于处理各种转换。tr刚执行时,字符串1中的字符被映射到字符串2中的字符,然后转换操作开始。
tr命令的一般格式:tr –c –d –s [ “string_to_translate_from” ] [ “string2_translate_to ] file
-c 用字符串1中字符集的补集替换此字符集
-d 删除字符串1中所有的输入字符
-s 输出有重复出现的字符序列,只保留第一个。
(1)删除重复出现的字符
$ tr –s “[a-z]” < file 去除文件file中所有重复字母
(2)删除空行
使用-s,换行的八进制表示为\012 或使用换行速记方式 \n。
$ tr –s “[\012]” < test.txt // 使用八进制方式
$ tr –s [“\n”] < test.txt // 使用转义字符
(3)大小写字母转换
$ echo “CHINA” | tr “[A-Z]” “[a-z]” // 转换成小写字母
$ echo “china” | tr “[a-z] “ “[A-Z]” // 转换成大写字母
$ cat file1 | tr “[A-Z]” “[a-z]” > file2 // 将文件file1大写转换成小写并输出至文件file2
(4)删除指定字符
结合使用- c和- s选项。
$ tr –cs “[A-Z][a-z]” “[\012*]” < file // 删除文件中所有数字,只保留字母。
(5)转换控制字符
tr的第一个功能就是转换控制字符,特别是从dos向UNIX转换。
使用 cat –v 显示控制字符。
$ cat –v test.txt
Zhou ^^^^^^12^M
Xu^^^^^^50^M
Hong^^^^100^M
^Z
‘^^^^^^’ 是tab键。每一行以Ctrl-M结尾,文件结尾Ctrl-Z。
查看ASCII表,^的八进制代码是136,^M是015,tab键是01,^Z是032
$ tr –s “[\136]” “[\011*]” < test.txt
$ tr –s “[\015\032]” [“\n”] < test.txt
1.7 sed
1.7.1 sed
概述
sed 是一种在线编辑器,它一次处理一行内容。处理时把当前处理的行存储在临时缓冲区中,称为模式空间(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。
可以通过定址来定位你所希望编辑的行,该地址用数字构成,用逗号分隔的两个行数表示以这两行为起止的行的范围,如1,3表示1、2、3行,美元符号$表示最后一行。范围可以通过数据,正则表达式或者二者结合的方式确定 。在sed语句,正则表达式必须封闭在//中间。在sed地址管理中默认是对全局进行操作,地址可以分为行地址和模式地址。如1,10d 12d 10,$d 表示行地址,如/^$/d 表示模式地址。用户在进行操作时,可以对行地址和模式地址结合进行操作。
1.7.2 Sed
命令
调用sed命令有两种形式:
sed [options] 'command' file(s)
sed [options] -f scriptfile file(s)
选项
-e command, --expression=command 允许多台编辑。
-h, --help 打印帮助,并显示bug列表的地址。
-n, --quiet, --silent 取消默认输出。
-f, --filer=script-fil 引导sed脚本文件名。
-V, --version 打印版本和版权信息。
(1)替换命令
语法格式:sed ‘s/old/new/flags’ file
文件file中内容old用new替换。
Flags:g表示对全局进行替换;w file:表示匹配行的内容写到另一个文件中。
例如:
$ sed ‘s/unix/Linux/g’ file 文件file中所有内容unix都用Linux替换
$ sed ‘s/unix/Linux/w 11’ file文件file中所有内容unix都用Linux替换并将结果写入11
(2)删除命令
语法格式:sed ‘[address]d’ file
删除文件file中address表达的内容
例如:
$ sed ‘/^\.aa/d’ file 删除文件file中以.aa开头的内容
$ sed ‘/^$/d’ file 删除文件file中空行的内容
$ sed ‘10d’ file 删除文件file中第10行的内容。
(3)追加命令
语法格式:sed ‘[address]a\text’ file
文件file中address表达的行后面添加text内容
例如:
$ sed '10a\abcd' file 在文件file中的第10行后面追加一行abcd字符
$ sed '/unix/a\abcd' file 在文件file中所有出现unix字符的行后面追加一行abcd字符
$ sed '/unix/a\abcd\n\dcba' file 在文件file中出现unix字符行后面追加两行字符:abcd和dcba。
(4)插入命令
语法格式:sed ‘[address]i\text’ file
文件file中address表达内容行前面插入text内容。
例如:$ sed '/unix/i\abcd´ file 在文件file中unix行前面插入abcd字符
(5)更改命令
语法格式:sed ‘[address]c\text’ file
文件file中address表达内容的行用text代替。
例如:$ sed '1c\aaaa' file 将文件file中第一行的内容更改为aaaa.
(6)打印行号
语法格式:sed ‘[address]=’ file
打印 文件file中address表达内容的行号
例如:
$ sed '/unix/=' file 打印文件file中包含unix字符的行号。不包含unix字符的行不打印行号。
(7)读写文件
语法格式:sed ‘[address]r file1’ file 文件file中address表达的内容后插入文件file1的内容
语法格式:sed ‘[address]w file1’ file 文件file中address表达的内容写入文件file2中
例如:
$ sed '/unix/r 11’ file 在文件file中unix字符的后面读入11文件的内容
$ sed '2r 11' file 在文件file的第2行后面读入11文件的内容
$ sed '2,5w 22' file 将文件file中第2行到第5行的内容写到22文件中去。
1.8 awk
1.8.1 awk
概述
awk是一种样式扫描与处理工具,与sed和grep很相似,但其功能却大大强于sed和grep,它几乎可以完成grep和sed所能完成的全部工作,同时它还可以可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。
awk是以三个创立者的名字(Aho、Peter Weinberg和Brain Kernighan)的缩写命名的,awk拥有自己的语言:awk程序设计语言。awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。awk抽取信息后才能进行其他文本操作。
1.8.2 Awk
调用
有三种方式可以调用awk
(1) awk命令行:awk [-F field-separator] ‘commands’ input-file(s)
[-F 域分隔符]是可选的,awk使用空格作为缺省的分隔符;commands是真正的awk命令;input-files是一个或多个输入文件。
(2)将所有的awk命令插入一个脚本文件并以 #!/bin/awk -f 作为首行,给予该脚本可执行权限,然后在shell下通过键入该脚本的脚本名调用之。
(3) 将所有的awk命令插入一个单独脚本文件,然后使用: awk -f awk-script-file input_file(s)
-f选项指明文件awk-script-file中的awk脚本,input-files是一个或多个输入文件。
awk命令的一般形式
awk ' BEGIN { actions }
awk_pattern1 { actions }
............
awk_patternN { actions }
awk END { actions }
其中 BEGIN { actions } 和 END { actions } 是可选的。
awk脚本文件
#!/bin/awk -f
BEGIN { print "this is the begin of awk script" }
{ print $1, $2, $3 }
END { print "this is the end of awk script" }
第一行是!/bin/awk -f。这很重要,没有它自包含脚本将不能执行。这一行告之脚本系统中awk的位置。通过将命令分开,脚本可读性提高,还可以在命令之间加入注释,使用“#”作为注释符,它使“#”到行尾的内容成为注释。
域和记录
awk执行时,其浏览域标记为$1、$2 . . . $n,这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。使用$ 1 , $ 3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,不必指明$ 1 , $ 2 , $ 3 , $ 4 , $ 5,可使用$ 0,意即所有域。
例子:
$ awk -F ":" '{print $1, $3, $6}' /etc/passwd 打印passwd文件的用户名、用户ID和用户目录
$ awk '/hongdy/{print}' /etc/passwd 显示文本文件passwd含有字符串hongdy的所有行。
流程控制结构
(1)if (condition) {then-body} [else {else-body}]
(2)while (condition) {body}
(3)do {body} while (condition)
(4)for (initialization; condition; increment) {body}
其中condition一般为布尔表达式,body和else-body是awk语句块。
1.8.3 awk
变量
在awk脚本中的表达式中要经常使用变量。不要给变量加双引号,因为awk将视之为字符串。awk的变量基本可以分为两类:awk内部变量和自动以变量。
1.8.3.1 awk
内部变量
awk的内部变量用于存储awk运行时的各种参数,这些内部变量又可以分为:
(1)自动内部变量:这些变量的值会随着awk程序的运行而动态的变化,在awk_script中改变这些变量的值是没有意义的(即不应该被赋值)。
常用的自动内部变量
变量 |
说明 |
NF |
当前输入字段的字段数 |
NR |
当前输入文件中已经被awk读取过的记录行的数目 |
FNR |
已经被awk读取过的记录行的总数目。只有一个输入文件时FNR和NR相等 |
ARGC |
命令行参数个数 |
FILENAME |
当前输入文件的文件名 |
ARGIND |
当前被处理的文件在数组ARGV内的索引 |
|
|
例子:
$ awk ‘{ print “filename=” FILENAME, “count=” NF}’ 11 假设文件11内容为123 abc。
Filename=11, count=2
(2)字段变量($0 $1 $2 $3 ...)
当awk把当前输入记录分段时,会对这些字段变量赋值。在awk运行过程中字段变量的值是动态变化的。可以创建新的输出字段,比如当前输入记录被分割为8个字段,这时可以通过对变量 $9 (或$9之后的字段变量)赋值而增加输出字段,NR的值也将随之变化。
字段变量支持变量名替换。
例子:
$ pwd | awk -F/ '{print $NF}' 打印输入记录的最后一个字段
如果当前目录为/home/hongdy/linux , awd 以/ 为分隔符,有三个字段,输入的最后一个字段为linux
$ awk '{x=2;print $x}' 11 打印输入记录的第2个字段
如果文件11的内容为zhou xu hong, 有三个字段,第二个字段即为xu
(3)其它内部变量
可以修改这些变量。常见的有:
变量 |
说明 |
FS |
输入记录的字段分隔符(默认是空格和制表符) |
OFS |
输出记录的字段分隔符(默认是空格) |
OFMT |
数字的输出格式(默认是 %.6g) |
RS |
输入记录间的分隔符(默认是NEWLINE) |
ORS |
输出记录间的分隔符(默认是NEWLINE) |
ARGV |
命令行参数数组 |
ENVIRON |
存储系统当前环境变量值的数组 |
|
|
例如:
$ cat /etc/passwd | awk 'BEGIN { FS=":" } {print "User name: "$1,"UID: "$3}'
文件/etc/passwd内容类似于 hongdy:x:501:501:hongdy:/home/hongdy:/bin/sh,以:为分隔符,打印用户名和用户ID。
1.8.3.2 自定义变量
(1)定义变量varname=value (自定义变量不需声明,赋值语句同时完成变量定义和初始化)
(2)表达式中出现不带双引号的字符串都被视为变量,如果未赋值默认值为0或空字符串。
1.8.4 Awk
函数
可以在awk_script的任何地方使用awk函数。awk函数可以分为内置函数和自定义函数。
1.8.4.1 awk
内置函数
(1)常见awk内置数值函数
函数名 |
说明 |
int(x) |
求出x 的整数部份,朝向0 的方向做舍去。eg: int(3.9)是3 |
sqrt(x) |
求出x 正的平方根值。eg: sqrt(4)=2 |
exp(x) |
求出x 的次方。eg: exp(2) 即是求e*e 。 |
log(x) |
求出x 的自然对数。 |
sin(x) |
求出x 的sine 值,x 是弪度量。 |
cos(x) |
求出x 的cosine 值,x 是弪度量。 |
rand () |
得到一个随机数(平均分布在0和1之间)。 |
srand(x) |
设定产生随机数的seed为x。 |
|
|
例子:$ awk '{ print log($1)}' 12 假设文件12的内容第一个域值是2,打印log2的值
(2)常见awk内置字符串函数
函数名 |
说明 |
index(in, find) |
返回字符串in中字符串find第一次出现的位置(索引从1开始),如果在字串in中找不到字符串find,则返回值为0。 |
length(s) |
求出字符串s的字符个数。eg: length("abcde") 是5。 |
match(s,r) |
r在字符串s的第一次出现的位置,如果s不包含r,则返回值0。 |
sprintf(fmt,exp1,...) |
返回模式字符串: 和printf类似印出 |
sub(p, r,t) |
在字符串t中寻找符合模式字符串p的最靠前最长的位置,并以字符串r代替最前的p。 |
substr(str, st, len) |
传回str的子字符串,其长度为len字符,从str的第st个位置开始。如果len没有出现,则传回的子字符串是从第st个位置开始至结束。 |
split(s,a,fs) |
在分隔符fs为分隔符将字符串s分隔成一个awk数组a,并返回a的下标数 |
tolower(str) |
将字符串str的大写字母改为小写字母 |
toupper(str) |
将字符串string 的小写字母改为大写字母 |
例子:$ echo "abcdefg" | awk '{print length($0)}' 打印字符串“abcdefg”的长度
(3)常见awk内置系统函数
函数名 |
说明 |
close(filename) |
将输入或输出的文件filename 关闭 |
system(command) |
此函数允许调用操作系统的指令,执行完后将回到awk程序 |
1.8.4.2 自定义函数
复杂的awk常常可以使用自己定义的函数来简化。调用自定义的函数与调用内置函数的方法一样。
自定义函数定义的格式:自定义函数可以在awk程序的任何地方定义。
function fun_name (parameter_list) { // parameter_list是以逗号分隔的参数列表
body-of-function // 函数体,是awk语句块
}
例子:
$ awk '{ print "sum =" SquareSum($1,$2) } function SquareSum(x,y) { sum=x*x+y*y ; return sum } ' 11
自定义了一个平方和的函数,从文件11中取出两个数,打印他们的平方和。
或者写到脚本文件里
$ vi awk_fun
#!/bin/awk -f
function SquareSum(x, y){ sum = x*x + y*y; return sum;}
{print "sum=", SquareSum($1, $2)}
$ chmod a+x awk_fun
$ ./awk_fun 11
sum=13 假设文件11的内容是2 3,平方和是13。
1.8.4.3 Awk
输出函数printf
awk提供函数printf,拥有几种不同的格式化输出功能,每一种printf函数都以一个%符号开始,以一个决定转换的字符结束。printf函数基本语法是printf([格式控制符],参数)。
例子:
$ awk '{ printf("%d %s\n", $1, $2) }' 11
123 abc 假设文件11的内容是数字123 和字符串abc,使用printf打印整型数和字符串。
符号 |
含义 |
双引号 |
可以引用除字符$ 、\ 外的任意字符或字符串 |
单引号 |
与双引号类似,不同的是shell会忽略任何引用值 |
反引号 |
设置系统命令的输出到变量,shell将反引号中的内容作为一个系统命令并执行 |
反斜线 |
屏蔽特殊含义 & * + $ ` “ | ? |
在执行某个命令的时候,有时需要依赖于前一个命令是否执行成功。比如:往某个文件夹写入文件,要先判断那个文件夹是否存在,否则无法写入文件。
如果希望在成功地执行一个命令之后再执行另一个命令,或者在一个命令失败后再执行另一个命令,&&和 | | 可以完成这样的功能。相应的命令可以是系统命令或shell脚本。Shell还提供了在当前shell或子shell中执行一组命令的方法,即使用()和{ }。
(1)使用 &&
&& 左边的命令返回真(即返回0,成功被执行)后,&& 右边的命令才能够被执行。
(2)使用 ||
|| 左边的命令未执行成功,|| 右边的命令才能够执行。
(3)用 () 和 {} 将命令结合在一起
为了在shell中执行一组命令,用命令分隔符隔开命令,并把所有的命令用()或{}括起来。
() 的一般形式: (命令1; 命令2;….)
{} 的一般形式: {命令1; 命令2; . . }
如果使用{}代替(),那么相应的命令将在子shell而不是当前shell中作为一个整体被执行。
例子:
$ [ -d test ] && rmkdir test // 如果当前目录下的test是个目录,则删除这个目录
$ [ -f test ] || touch test // 如果test不是一个正规文件,则创建一个文件
)if 语句
if then else 语句的一般格式:
if 条件1
then 命令1
elif 条件2
then 命令2
else 命令3
fi
使用if语句时,必须将then部分放在新行,否则会产生错误。如果不分行,必须使用命令分隔符。
vi if1.sh
#!/bin/sh
echo "Please input your name?"
read NAME
echo "Please input your ***?"
read ***
if [ $*** = "male" ] ; then
echo "Name: $NAME ***: male"
elif [ $*** = "female" ]; then
echo "Name: $NAME ***: female"
else
echo "Name: $NAME ***: unkonwn"
fi
程序提示用户输入姓名和性别,然后判断性别并打印结果。
)case 语句
case 语句的一般格式:
case 值 in
模式1}
命令1
…
;;
模式2}
命令2
…
;;
esac
例子:
$ vi case1.sh
#!/bin/sh
echo -n "Enter a number from 1 to 3:"
read NUM
case $NUM in
1) echo "your select 1"
;;
2) echo "your select 2"
;;
3) echo "your select 3"
;;
*) echo "your select out 1-3"
;;
esac
程序提示用户输入选择,然后打印用户的选择。
)for循环
For循环的一般格式:
for 变量名 in 列表
do
命令1
命令2
done
for循环不使用in列表选项,接受命令行位置参数作为参数,查看特定参数$@ 或 $*,已从命令行中取得参数
for param in "$@" or for param in "$*"
例子:
vi for1.sh
for loop in 1 2 3 4 5
do
echo $loop
done
)while循环
While循环用于不断执行一系列命令,也用于从文件中读取数据。
While循环的一般格式:
while 命令
do
命令1
命令2
...
done
例子:
$ vi while1.sh
#!/bin/sh
COUNTER=0
while [ $COUNTER -lt 5 ]
do
COUNTER=`expr $COUNTER + 1`
echo $COUNTER
done
COUNTER初始化为0,然后每次加1并打印,直到COUNTER小于5。
test一般有两种格式:test condition 或 [condition]
文件状态有:
(1)-d目录;(2)-s非空;(3)-f正规文件;(4)-L符号连接;
(5)-r可读;(6)-w可写;(7)-x可执行
例子:
$ ls –al test.file
-rw-r-r-- test.file
$ test -w test.file 或 [ -w test.file ]
$ echo $?
测试时可使用逻辑操作符
(1)-a逻辑与: 操作符两边均为真,结果为真,否则为假。
(2)-o逻辑或: 操作符两边一边为真,结果为真,否则为假。
例子:
$ [ -w file1 -a –w file2 ]
$ echo $?
字符串测试的一般格式:[ string1 string_operation string2 ]
字符串操作符有:
(1)= 两个字符串相等; (2)!= 两个字符串不相等
(3)-z 空串 (4)-n 非空串
例子:
$ [ -z $EDITOR ] 测试环境变量EDITOR是否为空
$ echo $?
数值测试的一般格式:["number" numeric_operator "number" ]
数值操作符有:
(1)-eq数值相等; (2)-ne数值不相等;
(3)-gt第一个数大于第二个数; (4)-lt第一个数小于第二个数;
(5)-le第一个数小于等于第二个数; (6)-ge第一个数大于等于第二个数
例子:
$ [ 31 -eq 31 ]
$ echo $?
expr用法
expr命令一般用于整数值,但也可用于字符串。
expr的一般格式:expr argument operator argument
例子:
$ expr 10 + 10 数值前后要有空格
$ expr 30 / 3
$ expr 20 \* 3 // 使用乘号时必须用反斜线屏蔽其特定含义
expr在循环中用于增量计算。首先循环初始化为0,然后循环值加1,反引号的用法意即替代命令。
最基本的一种是从(expr)命令接受输出并将之放入循环变量。
例子:
$ LOOP = 0 等于号前后不能有空格
$ LOOP = `expr $LOOP + 1` 加号前后要有空格
$ echo $LOOP 打印LOOP值
1
函数
函数由两部分组成: 函数标题 和 函数体。
标题是函数名,标题名应该唯一;函数体是函数内的命令集合。
定义函数的格式为:
定义函数也可在函数名前加function。所有函数在使用前必须定义,一般将函数放在脚本开始部分。调用函数仅使用其函数名即可。
例子:
vi function1.sh
my_date ()
{
echo “Today’s date is `date` “
}
echo “now execute function my_date”
my_date
$ sh function1.sh
Now execute function hello
Today's date is Wed Feb 27 22:48:21 CST 2008
定义一个my_date函数,主要功能是打印当前的日期时间,然后执行这个函数。
定位shell函数:. function.sh
使用shell函数:function_name
删除shell函数:unset function_name
例如:
$ . function1.sh 定位shell函数
$ set | grep my_date 在set环境变量里查看函数my_date是否被载入
my_date()
$ my_date 使用shell函数
Today's date is Wed Feb 27 22:48:21 CST 2008
$ unset my_date 删除shell函数
$ set | grep my_date 在set环境变量里查看函数my_date是否存在
向函数传递参数
向函数传递参数就像在一般脚本中使用特殊变量$ 1 , $ 2 . . . $ 9一样,函数取得所传参数后,将原始参数传回shell脚本,因此最好先在函数内重新设置变量保存所传的参数。函数调用参数的转换以下划线开始,后加变量名,如_name.
从调用函数中返回
当函数完成处理或希望函数基于某一测试语句返回时,可做两种处理:
1) 让函数正常执行到函数末尾,然后返回脚本中调用函数的控制部分。
2) 使用return返回脚本中函数调用的下一条语句,可以带返回值,0为无错误,1为有错误。
可以直接在脚本调用函数语句的后面使用最后状态命令($?)来测试函数的返回值。
尊重原创!
本文出自 “zxuhong” 博客,请务必保留此出处http://zxuhong.blog.51cto.com/368977/73527