第十五章 呈现数据
1.Linux的三个标准文件描述符
标准输入(0)STDIN ,标准输出(1)STDOUT ,标准错误(2)STDERR
2.重定向输出
重定向到文件描述符时,必须在文件描述符数字前加一个 &
临时重定向:
例:
$ cat test1
#!bin/bash
echo "This is an error" >&2
echo "This is normal output"
$
$ ./test1 2 > test2
This is normal output
$ cat test2
This is an error
永久重定向:
exec 告诉shell在脚本执行期间重定向某个特定文件描述符。
例:
#exec 1>testout
exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。
3.重定向输入
例:
exec 0 < testfile
这个命令告诉shell应该从文件testfile中获得输入,而不是STDIN。
4.重定向错误
例:badfile文件不存在。
ls -al badfile 2>test4
文件不存在的错误消息不会出现在屏幕,而被写到了test4文件里。
5.创建自己的重定向
1.创建输出文件描述符:
exec 3>testout
echo “hello world”>&3
文件描述符3重定向到testout文件,”hello world”输出到testout文件里。
2.创建输入文件描述符:
例:
exec 6<&0
exec 0<testfile
命令内容
….
exec 0<&6
read answer
先用文件描述符6来保存STDIN的位置,然后将STDIN重定向到testfile文件,read命令
的所有输入都来自重定向后的STDIN(Y也就是输入文件testfile)
6.关闭文件描述符
shell在脚本退出时自动关闭文件描述符,如果想在脚本结束前手动关闭文件描述符,
要将它重定向到特殊符号&- 。
例:
exec 3>&-
关闭文件描述符3。
7.列出打开的文件描述符
lsof 可列出整个Linux系统打开的所有文件描述符。
8.阻止命令输出
Linux系统上的null文件位置是 /dev/null
shell输出到null文件的任何数据都不会保存,全部被丢弃。
例:常用清空日志文件的方法:
cat /dev/null > testfile
9.创建本地临时文件
mktemp 文件名.XXXXXX(六个大写的X)
-t 选项强制在系统的临时目录来创建文件
-d 创建一个临时目录
10.记录消息
tee filename
tee命令相当于管道的T型接头,从STDIN过来的数据同时发往两处。一处是STDOUT,一处
是tee命令行所指定的文件名。(-a 选项将数据追加到文件中)
第十六章 控制脚本
1.Linux 常见信号
Linux 终端输入 kill -l 可列出所有信号
2.生成信号
中断进程:
Ctrl + C :结束当前进程,发送信号SIGINT
暂停进程:
Ctrl + Z :变成后台进程,发送信号SIGSTOP
退出进程:
Ctrl + / :退出当前进程,发送信号 SIGQUIT
杀死进程:
kill -9 +PID 发送一个SIGKILL 信号来终止指定的进程。
3.捕获信号
用trap来捕获信号
格式:
trap 命令 信号
例:在脚本中有
trap "hello world" SIGINT
每次使用Ctrl + C组合键,都会输出"hello world",而脚本并未停止。
例:捕获shell脚本的退出
trap "echo Goodbye..." EXIT
当脚本运行到正常退出的位置时,捕获就会触发。
4.修改或移除捕获
删除已设置好的捕获:加双破折号选项
例:
trap "exit,bye..." SIGINT
命令
....
trap -- 信号(如SIGINT)
删除之前设置捕获SIGINT信号,当按下Ctrl + C键,脚本就立刻终止。
5.后台模式运行脚本
在命令后面加个 & 符号。
例: $ ./test.sh &
放到后台运行
6.作业控制
作业控制:启动、停止、终止以及恢复作业的功能。
1.查看作业
用jobs命令查看shell当前正在处理的作业。
选项:
-l 列出进程的PID以及作业号
-p 只列出作业的PID
-r 只列出运行中的作业
-s 只列出已停止的作业
2.重合停止的作业
后台模式重启作业:bg + 作业号
前台模式重启作业:fg + 作业号
7.调整谦让度
调度优先级为整数,范围-20 ~ +19(-20为最高级),bash shell默认以优先级0来启动
所有进程。
nice和renice命令可改变调度优先级。前者只能降低优先级。
例:
renice -n 10 -p 5055
将PID为5055的进程的调度优先级调为10。
8.定时运行作业
- at
at 命令格式:
at [-f filename] time (-f 指定读取命令的文件名)
时间格式:10:15 、10:15PM 、now 、noon、midnight等。
删除作业:用atrm 命令来删除。
2.安排定期执行的脚本(cron 表)
cron表格式:
min hour dayofmonth month dayofweek command
记为:分 时 日 月 周 命令
例子:
每晚的21:30重启apache。
30 21 * * * /usr/local/etc/rc.d/lighttpd restart
每月1、10、22日
45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart
每天早上6点10分
10 6 * * * date
每两个小时
0 */2 * * * date
晚上11点到早上8点之间每两个小时,早上8点
0 23-7/2,8 * * * date
1月份日早上4点
0 4 1 jan * date
3.构建cron时间表
Linux系统提供了crontab命令来处理cron时间表。
浏览cron目录
$ ls /etc/cron.*ly
如果脚本需要每天,将脚本复制到daily目录,cron就会每天执行它。
第十七章 创建函数
1.shell脚本函数(function)
shell 函数定义:
第一种格式:
function 函数名()
{
command
}
第二种格式:
函数名()
{
command
}
shell 函数特点:
1.没有返回值类型
2.没有参数列表
函数定义完之后必须要调用,否则不会执行函数中的语句。在函数被定义前使用函数,会报错。
函数调用形式:
1.函数名 参数 //无返回值调用
2.返回值=函数名 参数
//有返回值调用
2.返回值
默认退出状态码(范围0 ~ 255)
用 $? 查看函数最后一条命令是否运行成功,但这比较危险。return命令
退出函数并返回特定的退出状态码。使用函数输出(echo)
例:
function test{
read -p "Enter a value:" value
echo $[ $value * 2]
}
通过这种技术可以返回浮点值和字符串值。
3.向函数传递参数
例:
# $# 获取参数个数,$1、$2 获取参数值,$@获取参数内容
function addem{
if[ $# -eq 0 ] || [ $# -gt 2 ]
then
echo -1;
elif [ $# -eq 1 ]
then
echo $[$1 + $1]
else
echo $[$1 + $2]
fi
}
调用时,value = $(addem 10 15 20)
echo $value
4.函数中的变量
全局变量:默认情况下,shell脚本中定义的任何变量都是全局变量。
局部变量:加关键字 local 修饰。
5.数组变量和函数
例:
array=(1 2 3 4 5)
func $array //此时只传递数组的第一个数过去
正确做法:
func ${array[*]}
6.函数递归
例:求n的阶乘
function factorial{
if [ $1 -eq 1 ]
then
echo 1
else
local temp=$[$1 -1]
local result=`factorial $temp`
echo $[$result * $1]
}
7.创建库
在shell脚本中可用source命令来运行库文件脚本。source命令有个快捷的别名,称作点操作符。在shell脚本中运行myfuncs库文件,只需添加:
. ./myfunc
8.在命令行上创建函数
第一种方法:
$ function divem {echo $[$1 / $2];} //必须在每个命令后面加分号,命令的起止
$ divem 100 5
$ 20
$
9.在.bashrc文件中定义函数
把自己的函数放在.bashrc文件末尾,下次启动shell时,库中的所有函数都可以在命令界面下使用,也可以用source命令添加到脚本中。
第十九章 初始sed和gawk
1.sed 的使用
sed编辑器不会修改文本文件的数据
命令格式:
sed option script file // 选项 脚本 文件
多个命令加-e,必须用分号隔开
$ sed -e 's/abc/def; s/fgh/ijk/' test.txt
选项:
-f file 将file中指定的命令添加到已有的命令中
-n 不打印所有的行列到标准输出
d 删除行
i 在当前行之前插入行
a 在当前行之后添加一行或多行
c 修改行
l 列出非打印字符
替换选项:
s 用一个字符替换另外一个字符
g 表明新文本会替换所有匹配的文本
p 打印行
w file 替换的结果写到文件中
使用地址:
数字形式表示区间和文本模式过滤出行。
例:
1.替换命令:
sed 's/abc/def/g' file 把文本内的所有的abc替换成def,没有g 则只替换行内第一个abc
sed -n 's/abc/def/p' file 只打印发生替换的那些行
2.删除:
sed '3,$d' file 删除从第3行到末尾的内容
sed '3d' file 删除第三行的内容
sed '/abc/d' file 删除包含abc的行
3.插入和附加文本:
格式:
sed '[address]command\ new line'
sed 'abc/i\def' file 在包含abc的行前插入一行,写入def
用a 附加插入到后面
sed 'abc/a\def' file
4.写入文件:
格式:
[address]w filename
sed '1,2w test.txt' data.txt 把data.txt文件的第1、第2行写入到文件test.txt里
5.修改行
sed '/abc/c\def' file 在包含abc的行替换成def
6.打印行号
sed '=' file
2.awk
文本模式搜索扫描指令,可以根据指定分割字符把数据行分解多个字段,可以输出数据行的某个字段。
域:称为字段,行数据分解成小数据段
awk 语法:
awk -F 分割字符 '{执行处理语句}' 文件名
-F:指定分割字符,如果不写,默认空格为分割字符
'{执行处理语句}':分成三个部分:'BEGIN{} {} END{}'
'BEGIN{}':语句只会执行一次,是在扫描数据行之前执行,强制awk在读取数据前执行BEGIN关键字后指定的程序脚本
'END{}' :语句只会执行一次,在awk读完数据后执行
'{}':多次执行,每扫描一行数据执行一次
选项:
-F FS 定义字段分隔符
-f file 从指定的文件中读取程序
awk 每行数据分解成多个域之后,用$1 $2 ..$3 表示分解的域.$0表示行
[root@localhost shell]# awk -F , '{print $4}' awkdata.txt
[root@localhost shell]# awk -F , '{print $0}' awkdata.txt
[root@localhost shell]# awk -F : '{print $1}' /etc/passwd
[root@localhost shell]# awk '{print $1}' awkdata.txt
[root@localhost shell]# cat awkdata.txt | awk -F , '{print
$2}'
BEING{}
[root@localhost shell]# awk -F , 'BEGIN{print "name"}{print
$4}' awkdata.txt
END{}
[root@localhost shell]# awk -F , 'BEGIN{print "score"}{print
$5}END{print "end"}' awkdata.txt
awk 使用if 判断
[root@localhost shell]# awk -F , '{if($3>48310) print $0}'
awkdata.txt
[root@localhost shell]# awk -F , '{if($3>48310) print $0 ; else print "no"}' awkdata.txt
awk 变量
1.自定义变量
2.内置变量
自定义变量 注意:
1.不存数据类型
2.可以在不同语句块使用(BEGIN) 初始化变量值 END 变量最终结果)
内置变量(awk内部定义多个变量)
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk读取的文件名
FNR 当前文件已处理的记录行数
FS 设置域分隔符,相当于-F
NF 域的列数 $NF标识最后处理域
NR 已处理的记录总行数
OFS 设置输出字段域分隔符
RS/ORS 换行符
第二十章 正则表达式
正则表达式即为自己定义的模式模板,Linux工具可以用它来过滤文本。
正则表达式类型:
1.基础正则表达式(BRE)
* 号:匹配前面一个普通字符的0次或多次重复。
例:
hel*o
则匹配helo、hello、helllo等字符。
. 号:匹配任意一个字符。
例: ...73.
则abc738 、4i973u都能匹配。
^ 号:匹配行首。
例:^cloud (表示已cloud开头的行)
$ 号:匹配行尾。
例:bye$ (表示匹配以bye结尾的所有行)
^$ :表示空行。
[]:集合,列举值.[abcd] [a-z] [A-Z] [0-9] [A-Z0-9]
[^]:除开列举之[^0-9] [^a-zA-Z]
例:
[0-9]匹配任意一个数字
[a-z]匹配所有小写字母
[A-Z]匹配所有大写字母
[^b-d]匹配不在b~d范围内的其他字符
\ 符号:转移符,用于屏蔽一个元字符的特殊意义
"\<\>":精确匹配
例:\<the\> 精确匹配the这个单词
2.扩展正则表达式
? 号:表明前面的字符出现0次或1次。
例:
JO?B 即匹配JOB或JOOB
+ 号:表明前面的字符出现1次或多次,但必须至少出现1次。
花括号{} :
{m}:表明前面字符精确出现m次。
{m,n}:表明前面字符至少出现m次,最多n次。
圆括号()分组(和"|"号搭配):
例:
re(a|e|o)d
则匹配read或reed或reod。
使用正则表达式间隔时,必须使用–re-interval命令行选项
第二十一章 sed进阶
1.多行命令
三个特殊命令:
N :将数据流中的下一行加进来创建一个多行组来处理。
D:删除多行组中的一行。
P:打印多行组中的一行。
例:data.txt 文本内容为
This is the header line.
This is the first data line.
This is the second data line.
合并文本2和3行:
$ sed '/first/{N ;s/\n/ /}' data.txt
This is the header line.
This is the first data line. This is the second data line.
$
排除命令(感叹号! 来排除):
$ sed -n '/header/!p' data.txt
This is the first data line.
This is the second data line.
$
多行删除命令(D 和 N 搭配使用):
例:
data1.txt内容为
On Tuesday,the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
删除命令:
$ sed 'N ; /System\nAdministrator/D' data1.txt
Administrator's group meeting will be held.
All System Administrators should attend.
$
注意:只删除模式空间的第一行,删除到换行符为止的所有字符。
多行打印:
$ sed -n 'N ; /System\nAdministrator/P' data1.txt
On Tuesday,the Linux System
$
2.保持空间
模式空间: sed编辑器保存文本的空间,保存待检查的文本。
保持空间: 缓冲区域,用来临时保存一些行。
sed编辑器的保持空间命令:
h 将模式空间复制到保持空间
H 将模式空间附加到保持空间
g 将保持空间复制到模式空间
G 将保持空间附加到模式空间
X 交换模式空间和保持空间的内容
反转数据流的文本行:
$ sed -n '{1!G ; h ; $p}' data1.txt
All System Administrators should attend.
Administrator's group meeting will be held.
On Tuesday,the Linux System
$
3.改变流
分支(branch)命令格式:
[address]b [label]
address参数决定了哪些行的数据会触发分支命令,label参数定义了要跳转的位置
例:data.txt 文本内容为
This is the header line.
This is the first data line.
This is the second data line.
$ sed '{/fiirst/b jump1 ; s/This is the /NO jump on/
> :jump1
> s/This is the/Jump here on}' data.txt
No jump on header line
Jump here on first data line
No jump on second data line
$
跳转命令指定如果文本行中出现了first,程序就跳到jump1的脚本行。
4.模式代替
1. & 符号
&符号可用来代表替换命令中的匹配的模式。
例:
$ echo "The cat sleeps in his hat"| sed 's/.at/"&"/g'
The "cat" sleeps in his "hat".
$
5.创建sed实用工具
向文本文件的行间插入空白行:
$ sed 'G' data.txt
This is the header line.
This is the first data line.
This is the second data line.
$
不想在最后一行加空白行,则加排除号(!)和尾行符号($)
$ sed '$!G' data.txt
This is the header line.
This is the first data line.
This is the second data line.
$
给文件中行编号:
$ sed '=' data.txt | sed 'N ;s/\n/ /'
1 This is the header line.
2 This is the first data line.
3 This is the second data line.
$
打印末尾行:
$ sed -n '$p' data.txt
This is the second data line.
删除连续的空白行:
例:
data2.txt 文件内容为:
This is line one.
This is line two.
This is line three.
技巧:用区间,/. 到/^$/。
$ sed '/./,/^$/!d' data2.txt
This is line one.
This is line two.
This is line three.
$
第二十二章 gawk进阶
gawk支持两种不同类型变量:
- 内建变量
自定义变量
1.内建变量
FIELDWIDTHS 由空格分隔的一列数字,定义每个数字段的宽度
FS 输入字段分隔符
RS 输入记录分隔符
OFS 输出字段分隔符
ORS 输出记录分隔符
NF 字段总数 $NF标识最后处理域
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 当前shell环境变量及其值组成的关联数组
FILENAME awk读取的文件名
FNR 当前文件已处理的记录行数
NR 已处理的记录总行数
例:
[root@localhost windowshare]# cat data
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,daya32,data33,data34,data35
[root@localhost windowshare]# gawk 'BEGIN{FS=","; OFS="--"}{print $1,$2,$3}' data
data11--data12--data13
data21--data22--data23
data31--daya32--data33
说明:FS 设置了分隔符为",",OFS设置了"--"来分隔输出字段
[root@localhost windowshare]# gawk 'BEGIN{FS=","; OFS="--"}{print $1,$NF}' data
data11--data15
data21--data25
data31--data35
说明:NF可以在不知道具体位置的情况下指定记录中的最后一个数据字段。
获取行数:FNR 和NR的区别
[root@localhost windowshare]# gawk 'BEGIN{FS=","}{print $1,"FNR="FNR,"NR="NR}' data data
data11 FNR=1 NR=1
data21 FNR=2 NR=2
data31 FNR=3 NR=3
data11 FNR=1 NR=4
data21 FNR=2 NR=5
data31 FNR=3 NR=6
说明:FNR的值在处理每个数据文件时会被重置,而NR的值会继续计数到处理完所有的数据文件。
[root@localhost windowshare]# gawk -v n=2 'BEGIN{print ARGC,ARGV[0],ARGV[1]}' data
2 gawk data
2.自定义变量
变量命名要求:任意的字母、数字、下划线,不能以数字开头。
1.在脚本中给变量赋值
例:
[root@localhost windowshare]# gawk 'BEGIN{x=1;x=x * 2+1;print x}'
3
2.命令行上给变量赋值
例:
[root@localhost windowshare]# cat script1
BEGIN{FS=","}
{print $n}
[root@localhost windowshare]# cat data
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,daya32,data33,data34,data35
[root@localhost windowshare]# gawk -f script1 n=2 data
data12
data22
daya32
-v命令行允许在BEGIN代码之前设定变量
例:
[root@localhost windowshare]# gawk -v n=3 -f script1 data
data13
data23
data33
3.处理数组
数组变量赋值格式:
var[index] = element
var为变量名,index为关联数组的索引值,element为数据元素值。
例:
[root@localhost windowshare]# gawk 'BEGIN{array["shun"] = "hello"
> array[1]=100
> print array["shun"],array[1]}'
hello 100
遍历数组变量
用for语句的一种特殊形式
for (var int array)
{
statements
}
记住,var存放的是索引值而不是数组元素值
例:
[root@localhost windowshare]# gawk 'BEGIN{
> var["a"] = 1
> var["b"] = 2
> var["c"] = 3
> var[8] = 4
> for (test in var)
> {
> print "Index:",test,"- Value:",var[test]
> }
> }'
Index: 8 - Value: 4
Index: a - Value: 1
Index: b - Value: 2
Index: c - Value: 3
删除数组变量:
delete array[index]
一旦从关联数组中删除索引值,就无法用它来提取元素
4.使用模式
- 1.正则表达式
记住:使用正则表达式时,正则表达式必须出现在它要控制的程序脚本的左括号前。
例:查找出现 23的那一记录,输出第一个字段值
[root@localhost windowshare]# cat data
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,daya32,data33,data34,data35
[root@localhost windowshare]# gawk 'BEGIN{FS=","} /23/{print $1}' data
data21
2.匹配操作符
匹配操作符允许将正则表达式限定在记录中的特定数据字段。匹配符是波浪线(~)。
例:
$1 ~ /^data/
表示列出第一个字段以文本data开头的所有记录。
[root@localhost windowshare]# cat data
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,daya32,data33,data34,data35
[root@localhost windowshare]# gawk 'BEGIN{FS=","} $2~/^data2/{print $0}' data
data21,data22,data23,data24,data25
可以用 ! 符号来排除正则表达式的匹配
$1 !~ /expression/
例:
[root@localhost windowshare]# gawk 'BEGIN{FS=","} $2 !~ /^data2/{print $0}' data
data11,data12,data13,data14,data15
data31,daya32,data33,data34,data35
3.数学表达式
常见数学表达式
x == y :值x等于y
x <= y 、 x < y 、x >= y、 x > y。
数学表达式必须完全匹配。
例:
[root@localhost windowshare]# gawk -F , '$1 == "data"{print $1}' data
[root@localhost windowshare]#
[root@localhost windowshare]# gawk -F , '$1 == "data11"{print $1}' data
data11
4.结构化命令
if语句
格式:
if(coondition)
statement
else
ststement
也可以放在一行,使用else时必须在if语句后使用分号
if(condition) statement1; else statement2
while 语句
格式:
while (condition)
{
statements
}
do-while语句
格式:
do
{
statements
}while(condition)
for语句
gawk编程语言支持C风格的for循环
for( variable assignment; condition; iteration process)
例:求每行记录平均值
[root@localhost windowshare]# cat data2
130 120 135
160 113 140
145 170 215
[root@localhost windowshare]# gawk '{
> total = 0
> for(i = 1;i < 4; i++)
> {
> total += $i
> }
> avg = total / 3
> print "Average:",avg
> }' data2
Average: 128.333
Average: 137.667
Average: 176.667
5.格式化打印
格式化打印命令,用printf。
格式:printf “format string”,var1,var2…
跟C语言的print用法一样。
6内建函数.
有数学函数、字符函数、时间函数等。
6.自定义函数
必须用function关键字。
function name([variables])
{
ststements
}
可用return语句或echo语句返回值
例:自己实现一个rand()函数
[root@localhost windowshare]# gawk '
> function myrand(limit)
> {
> return int(limit*rand())
> }
> BEGIN{printf "myrand is %d\n",myrand(100)}'
myrand is 23
[root@localhost windowshare]#
要想重复使用函数,可以创建函数库,用-f file 从指定的文件中读取程序。