flameboy的博客

喜欢交朋友,希望各位大佬们能多指点本菜鸟,相互交流、相互学习。

《Linux命令行与shell脚本编程大全》笔记二

第十五章 呈现数据

1.Linux的三个标准文件描述符

标准输入(0)STDIN ,标准输出(1)STDOUT ,标准错误(2)STDERR

2.重定向输出

重定向到文件描述符时,必须在文件描述符数字前加一个 &

临时重定向:
例:

永久重定向:

exec 告诉shell在脚本执行期间重定向某个特定文件描述符。

例:

#exec 1>testout

exec命令会启动一个新shell并将STDOUT文件描述符重定向到文件。

3.重定向输入

例:

这个命令告诉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.定时运行作业

  1. 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  filefile中指定的命令添加到已有的命令中
-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.

合并文本23行:
$ 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可以在不知道具体位置的情况下指定记录中的最后一个数据字段。

获取行数:FNRNR的区别
[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 从指定的文件中读取程序。
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

《Linux命令行与shell脚本编程大全》笔记二

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭