Shell第二篇:正则表达式和文本处理工具

一 什么是正则

  正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法。或者说:正则就是用来描述一类事物的规则。

生活中处处都是正则:

    比如我们描述:4条腿

      你可能会想到的是四条腿的动物或者桌子,椅子等

    继续描述:4条腿,活的

          就只剩下四条腿的动物这一类了

 

在linux中,通配符是由shell解释的,而正则表达式则是由命令解释的,下面我们就为大家介绍三种文本处理工具/命令:grep、sed、awk,它们三者均可以解释正则。

二 grep

参数

-n  :显示行号
-o  :只显示匹配的内容
-q  :静默模式,没有任何输出,得用$?来判断执行成功没有,即有没有过滤到想要的内容

-l  :如果匹配成功,则只将文件名打印出来,失败则不打印,通常-rl一起用,grep -rl 'root' /etc 
-A  :如果匹配成功,则将匹配行及其后n行一起打印出来
-B  :如果匹配成功,则将匹配行及其前n行一起打印出来
-C  :如果匹配成功,则将匹配行及其前后n行一起打印出来
--color
-c  :如果匹配成功,则将匹配到的行数打印出来
-E  :等于egrep,扩展
-i  :忽略大小写

-v  :取反,不匹配
-w:匹配单词

[root@MiWiFi-R3-srv ~]# cat a.txt 
root123
ROot asdf
Root_123
rOOtss
root 123
[root@MiWiFi-R3-srv ~]# grep -i "root" a.txt 
root123
ROot asdf
Root_123
rOOtss
root 123
[root@MiWiFi-R3-srv ~]# grep -w "root" a.txt 
root 123

 

grep种类
grep
fgrep
pgrep
egrep

正则介绍

^ 行首
$ 行尾
. 除了换行符以外的任意单个字符
* 前导字符的零个或多个
.* 所有字符
[] 字符组内的任一字符
[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)
^[^] 非字符组内的字符开头的行
[a-z] 小写字母
[A-Z] 大写字母
[a-Z] 小写和大写字母
[0-9] 数字
\< 单词头 单词一般以空格或特殊字符做分隔,连续的字符串被当做单词
\> 单词尾

扩展正则 sed 加 -r 参数 或转义
grep 加 -E 或 egrep 或转义
AWK 直接支持 但不包含{n,m}
可以使用--posix支持
[root@MiWiFi-R3-srv ~]#  awk '/ro{1,3}/{print}' /etc/passwd
[root@MiWiFi-R3-srv ~]#  awk --posix '/ro{1,3}/{print}' /etc/passwd

sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前导字符零个或一个
+ 前导字符一个或多个
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出现m次
x\{m,\} x出现m次至多次(至少m次)
x\{m,n\} x出现m次至n次

posix定义的字符分类

[:alnum:] Alphanumeric characters.
匹配范围为 [a-zA-Z0-9]
[:alpha:] Alphabetic characters.
匹配范围为 [a-zA-Z]
[:blank:] Space or tab characters.
匹配范围为 空格和TAB键
[:cntrl:] Control characters.
匹配控制键 例如 ^M 要按 ctrl+v 再按回车 才能输出
[:digit:] Numeric characters.
匹配所有数字 [0-9]
[:graph:] Characters that are both printable and visible. (A space is print-
able, but not visible, while an a is both.)
匹配所有可见字符 但不包含空格和TAB 就是你在文本文档中按键盘上能用眼睛观察到的所有符号
[:lower:] Lower-case alphabetic characters.
小写 [a-z]
[:print:] Printable characters (characters that are not control characters.)
匹配所有可见字符 包括空格和TAB
能打印到纸上的所有符号
[:punct:] Punctuation characters (characters that are not letter, digits, con-
trol characters, or space characters).
特殊输入符号 +-=)(*&^%$#@!~`|\"'{}[]:;?/>.<,
注意它不包含空格和TAB
这个集合不等于^[a-zA-Z0-9]
[:space:] Space characters (such as space, tab, and formfeed, to name a few).

[:upper:] Upper-case alphabetic characters.
大写 [A-Z]
[:xdigit:] Characters that are hexadecimal digits.
16进制数 [0-f]

使用方法:
[root@seker ~]# grep --color '[[:alnum:]]' /etc/passwd

正则表达式及字符处理
目标文件/etc/passwd,使用grep命令或egrep
1.显示出所有含有root的行:
2.输出任何包含bash的所有行,还要输出紧接着这行的上下各两行的内容:
3.  显示出有多少行含有nologin。
4.显示出那些行含有root,并将行号一块输出。
5.显示出文件中
6.新建用户abominableabominateanomieatomize编写正则表达式,将他们匹配出来egrep 'a.omi(nabl|nat|z|)e' /etc/passwd
7.建四个用户Alex213sbWpq2222byH438PIGegon666egon过滤出用户名组成是字母+数字+字母的行
[root@MiWiFi-R3-srv ~]# egrep '^[a-Z]+[0-9]+[a-Z]+' /etc/passwd
8.显示出/etc目录下所有包含root的文件名
9. 过滤掉/etc/ssh/sshd_config内所有注释和所有空行
grep -v '^#' /etc/ssh/sshd_config |grep -v '^ *$'
grep作业

三 sed

sed
流编辑器 stream editer,是以行为单位的处理程序

sed 流编辑器 stream editer

语法
sed [options] 'command' in_file[s]
options 部分
-n
-e
-i
-f
command 部分
'[地址1,地址2] [函数] [参数(标记)]'

定址的方法 1.数字 2.正则
数字
十进制数
1 单行
1,3 范围 从第一行到第三行
2,+4 匹配行后若干行
4,~3 从第四行到下一个3的倍数行
2~3 第二行起每间隔三行的行
$ 尾行
1! 除了第一行以外的行
正则
正则必须用//包裹起来
扩展正则需要用 -r 参数或转义

数字定址:sed -n '1p' /etc/passwd

正则定址:sed -n '/^root/p' /etc/passwd

正则介绍

^ 行首
$ 行尾
. 除了换行符以外的任意单个字符
* 前导字符的零个或多个
.* 所有字符
[] 字符组内的任一字符
[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)
^[^] 非字符组内的字符开头的行
[a-z] 小写字母
[A-Z] 大写字母
[a-Z] 小写和大写字母
[0-9] 数字
\< 单词头 单词一般以空格或特殊字符做分隔,连续的字符串被当做单词
\> 单词尾

扩展正则 加 -r 参数 或转义
sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前导字符零个或一个
+ 前导字符一个或多个
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出现m次
x\{m,\} x出现m次至多次(至少m次)
x\{m,n\} x出现m次至n次


函数
增删改
a 后插
c 替换
i 前插
d 删除
输入输出
p 打印匹配的行 一般和 -n 参数连用,以屏蔽默认输出
r 从文件中读入
w 写入到文件中
控制流
! 命令取反 例: 1!d 删除第一行以外的行
{} 命令组合 命令用分号分隔 {1h;G} 可以理解为 -e 参数的另一种写法

= 打印行号(输入行的号码,而非处理的次数行号) 例如: sed -n '2{=;p}' infile
n 读入下一行到模式空间 例:'4{n;d}' 删除第5行
N 而是追加下一行到模式空间,再把当前行和下一行同时应用后面的命令

 

替换
s 字符串替换 s/old/new/

$ sed -n 's/root/ABCDEF/p' /etc/passwd

ABCDEF:x:0:0:root:/root:/bin/bash

operator:x:11:0:operator:/ABCDEF:/sbin/nologin

$ sed -n 's/root/ABCDEF/gp' /etc/passwd

ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash

operator:x:11:0:operator:/ABCDEF:/sbin/nologin

$ sed -n 's/root/ABCDEF/2p' /etc/passwd

root:x:0:0:ABCDEF:/root:/bin/bash

$ sed -n 's/root/ABCDEF/3p' /etc/passwd

root:x:0:0:root:/ABCDEF:/bin/bash

$ sed -n 's/root/ABCDEF/gp' /etc/passwd

ABCDEF:x:0:0:ABCDEF:/ABCDEF:/bin/bash

operator:x:11:0:operator:/ABCDEF:/sbin/nologin

$

\(\) 保存被匹配的字符 以备反向引用\N时使用 最多9个标签 标签顺序从左至右
& 替换时使用,在不定义标签时使用(反向引用)


试做:

删除第一个单词

删除最后一个单词

将第一个单词和最后一个单词兑换位置


y 字符替换(变形)

工作模式 模式空间和保持空间介绍


$ sed '1{p;p}' a.txt

11111111

11111111

11111111

22222222

33333333

44444444

55555555

66666666

$


置换 模式空间和保持空间(暂存空间)
h 把模式空间内容覆盖到保持空间中
H 把模式空间内容追加到保持空间中
g 把保持空间内容覆盖到模式空间中
G 把保持空间内容追加到模式空间中
x 交换模式空间与保持空间的内容

# cat test.sh
1111111
2222222
3333333
4444444
# sed '{1h;2,3H;4G}' ./test.sh
1111111
2222222
3333333
4444444
1111111
2222222
3333333
# sed '{1h;2x;3g;$G}' ./test.sh
1111111
1111111
2222222
4444444
2222222
#


试做题

将第一行插入到每个偶数行的后面

$ sed '1h;0~2G' a.txt

11111111

22222222

11111111

33333333

44444444

11111111

55555555

66666666

11111111

$

颠倒输出

$ sed '1!G;h;$!d' rev.txt

xyz

def

abc

$

脚本方法
-f 参数 引用脚本(脚本的末尾不能有空格制表符或其他文本)
# cat sed.sh
2,4d
s/777/seker/
s/999/seker&seker/
# sed -f sed.sh test.txt
1111111
5555555
6666666
seker7777
8888888
seker999seker9999
#

在脚本中指明解释器为sed
# cat sed.sh
#!/bin/sed -f
2,4d
s/777/seker/
s/999/seker&seker/
# ./sed.sh test.txt
1111111
5555555
6666666
seker7777
8888888
seker999seker9999
#

高级流控命令 b分支 t测试
分支命令用于无条件转移,测试命令用于有条件转移

分支 branch
跳转的位置与标签相关联
如果有标签则跳转到标签所在的后面行继续执行
如果没有标签则跳转到脚本的结尾处.
标签 以冒号开始后接标签名 不要在标签名前后使用空格
跳转到标签指定位置
[root@stu254 ~]# grep seker /etc/passwd
seker:x:500:500::/home/seker:/bin/bash
[root@stu254 ~]#
[root@stu254 ~]# grep seker /etc/passwd |sed ':top;s/seker/blues/;/seker/b top;s/5/555/'
blues:x:55500:500::/home/blues:/bin/bash
[root@stu254 ~]#

命令分析:让单次替换(cmd1)循环执行,直到条件不满足
:top; 定义一个top标签
s/seker/blues/; cmd1
/seker/b top; 如果模式匹配则跳转到top标签
s/5/555/ 当上一条模式不匹配时,既会继续执行这一条

选择执行
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash
[root@stu254 ~]#

zorro:x:501:501::/home/zorro:/bin/bash
[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;:end;s/5/666/'
zorro:x:6665501:501::/home/zorro:/bin/bash
[root@stu254 ~]#

命令分析: 执行cmd1,再去模式匹配,成功则跳转到cmd3开始执行,否则(模式不匹配)会按命令顺序逐个执行
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
:end;
s/5/666/ cmd3

另一种选择执行
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
blues:x:66600:500::/home/seker:/bin/bash

[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/blues/;/seker/b end;s/5/555/;b;:end;s/5/666/'
zorro:x:55501:501::/home/zorro:/bin/bash
[root@stu254 ~]#

命令分析: 执行cmd1;模式匹配cmd2成功则执行cmd3;否则执行cmd2,再跳转到脚本末尾
s/seker/blues/; cmd1
/seker/b end;
s/5/555/; cmd2
b;
:end;
s/5/666/ cmd3


测试命令,如果前一个替换命令执行成功则跳转到脚本末尾 (case结构)
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/bash

[root@stu254 ~]# grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t;s/home/DEF/;t;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash
[root@stu254 ~]#

与标签关联,跳转到标签位置
[root@stu254 ~]# grep 'seker' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
ABC:x:500:500::/home/seker:/bin/XYZ
[root@stu254 ~]#

[seker@seker ~]$ grep 'zorro' /etc/passwd |sed 's/seker/ABC/;t end;s/home/DEF/;t;:end;s/bash/XYZ/'
zorro:x:501:501::/DEF/zorro:/bin/bash

Sed作业:以/etc/passwd文件为模板1,删除文件每行的第一个字符。2,删除文件每行的第二个字符。3,删除文件每行的最后一个字符。4,删除文件每行的倒数第二个字符。5,删除文件每行的第二个单词。6,删除文件每行的倒数第二个单词。7,删除文件每行的最后一个单词。8,交换每行的第一个字符和第二个字符。9,交换每行的第一个字符和第二个单词。10,交换每行的第一个单词和最后一个单词。11,删除一个文件中所有的数字。12,删除每行开头的所有空格。13,用制表符替换文件中出现的所有空格。14,把所有大写字母用括号()括起来。15,打印每行3次。16,隔行删除。17,把文件从第2行到第5行复制到第7行后面。(选做题)18,把文件从第2行到第5行移动到第7行后面。(选做题)19,只显示每行的第一个单词。20,打印每行的第一个单词和第三个单词。21,将格式为    mm/yy/dd    的日期格式换成   mm;yy;dd22, a.txt内容ABCDEFXYZ通过SED实现tac命令tac a.txtXYZDEFABC1. sed -r 's/^(.)(.*)/\2/' /etc/passwd
2. sed -r 's/^(.)(.)(.*)/\1\3/' /etc/passwd
3. sed -r 's/(.*)(.)$/\1/' /etc/passwd
4. sed -r 's/(.*)(.)(.)$/\1\3/' /etc/passwd
5. sed -r 's/^([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\1\2\4/' /etc/passwd
6. sed -r 's/([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)$/\1\3\4/' /etc/passwd
7. sed -r 's/([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)$/\1\2\3/' /etc/passwd
8. sed -r 's/^(.)(.*)(.)$/\3\2\1/' /etc/passwd
9. sed -r 's/^(.)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\4\2\3\1\5/' /etc/passwd
10. sed -r 's/^([a-Z]+)([^a-Z]+)(.*)([^a-Z]+)([a-Z]+)$/\5\2\3\4\1/' /etc/passwd
11. sed -r 's/[0-9]//g' /etc/passwd
12. sed -r 's/^ *//g' /etc/passwd
13. sed -r 's/ /\t/g' /etc/passwd
14. sed -r 's/[A-Z]/(&)/g' /etc/passwd
15. sed 'p;p' /etc/passwd
16. sed '1~2d' /etc/passwd选做题17-18:文件内容
[root@MiWiFi-R3-srv ~]# cat test 
11111111111
2222222222
333333333
4444444444
55555555555
6666666666
777777777777
888888888888
9999999999999917.sed '2h;3,5H;7G' test 18. sed '2h;3,5H;2,5d;7G' test 19. sed -r 's/^([a-Z]+)([^a-Z]+)(.*)/\1/' /etc/passwd
20. sed -r 's/^([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]+)/\5\2\3\4\1\6/' /etc/passwd
21. 
22. sed -r '{1h;1d;2G;2h;2d;3G;3h}'
23. 
echo "2012/12/11" |sed -r 's/\//:/g'
echo "2012/12/11" |sed -r 's#\/#:#g'
echo "2012/12/11" |sed -r 's@\/@:@g'
sed作业

四 awk

awk -F: '$1 == "root"{print $1,NR,NF}' /etc/passwd
awk -F: 'NR>20 || NR<3{print $1,$3,$NF}' /etc/passwd
awk -F: 'NR>1 && NR<3{print $1,NR,NF}' /etc/passwd
awk -F: 'NR>1 && NR<4{print $1,NR,NF}' /etc/passwd
awk -F: '$1~/^r/{print $1,NR,NF}' /etc/passwd
awk -F: '/^root/{print $1,NR,NF}' /etc/passwd

 

username=root
awk -v var=$username -F: '$1 == var{print $1,NR,NF}' /etc/passwd

打印uid在30~40范围内的用户名。
打印第5-10行的行号和用户名
打印奇数行
打印偶数行
打印字段数大于5的行
打印UID不等于GID的用户名
打印没有指定shell的用户
awk作业

 

awk详细

语法
awk [options] 'commands' files
option
-F 定义字段分隔符,默认的分隔符是连续的空格或制表符
使用option中的-F参数定义间隔符号
用$1,$2,$3等的顺序表示files中每行以间隔符号分隔的各列不同域
NF变量表示当前记录的字段数
-v 定义变量并赋值 也可以借用次方式从shell变量中引入

 

command
读前处理 行处理 读后处理
1.读前处理 BEGIN{awk_cmd1;awk_cmd2}
2.行处理:定址 命令
定址方法: 正则,变量,比较和关系运算
正则需要用//包围起来
^ 行首
$ 行尾
. 除了换行符以外的任意单个字符
* 前导字符的零个或多个
.* 所有字符
[] 字符组内的任一字符
[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)
^[^] 非字符组内的字符开头的行
[a-z] 小写字母
[A-Z] 大写字母
[a-Z] 小写和大写字母
[0-9] 数字
\< 单词头 单词一般以空格或特殊字符做分隔,连续的字符串被当做单词
\> 单词尾

 

扩展正则 加 -r 参数 或转义
sed -n '/roo\?/p' /etc/passwd
sed -rn '/roo?/p' /etc/passwd
? 前导字符零个或一个
+ 前导字符一个或多个
abc|def abc或def
a(bc|de)f abcf 或 adef
x\{m\} x出现m次
x\{m,\} x出现m次至多次(至少m次)
x\{m,n\} x出现m次至n次

 

NR变量定址
NR 表示AWK读入的行数
FNR表示读入行所在文件中的行数
# awk '{print NR,FNR,$1}' file1 file2
1 1 aaaaa
2 2 bbbbb
3 3 ccccc
4 1 dddddd
5 2 eeeeee
6 3 ffffff
#
逻辑运算 可直接引用域进行运算
== >= <= != > < ~ !~
# awk 'NR==1 {print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#
3.命令 {print $0}
4.读后处理 END {awk_cmd1;awk_cmd2;}

 


AWK变量
NR 当前记录的个数(全部文件连接后的统计)
FNR 当前记录的个数(仅为当前文件的统计,非全部)
FS 字段分隔符 默认为连续空格或制表符,可以使用多个不同的符号做分隔符 -F[:/]
OFS 输出字符的分隔符 默认是空格
# awk -F: 'OFS="=====" {print $1,$2}' /etc/passwd
root=====x
NF 当前读入行的字段个数
ORS 输出记录分隔符 默认是换行
# awk -F: 'ORS="=====" {print $1,$2}' /etc/passwd
root x=====bin x=====
FILENAME 当前文件名

 

引用shell变量的方法
# a=root
# awk -v var=$a -F: '$1 == var {print $0}' /etc/passwd
或者 把整个命令拆开传递,让shell变量外露,
# awk -F: '$1 == "'$a'" {print $0}' /etc/passwd
# a=NF
# awk -F: '{print $'$a'}' /etc/passwd

 

操作符
赋值
= += -= /= *=
逻辑与 逻辑或 逻辑非
&& || !
匹配正则或不匹配,正则需要用 /正则/ 包围住
~ !~
关系 比较字符串时要把字符串用双引号引起来
< <= > >= != ==
字段引用
$ 字段引用需要加$,而变量引用直接用变量名取
运算符
+ - * / % ++ --
转义序列
\\ \自身
\$ 转义$
\t 制表符
\b 退格符
\r 回车符
\n 换行符
\c 取消换行

 


练习
打印uid在30~40范围内的用户名。
打印第5-10行的行号和用户名
打印奇数行
打印偶数行
打印字段数大于5的行
打印UID不等于GID的用户名
打印没有指定shell的用户
打印1..1000以内的7的倍数和包含7的数

 

流程控制
分支结构

 

if (条件) 动作
若有多个动作,则要用大括号将动作体包含起来 if (条件) {动作1;动作2}
# awk -F: '{if ($1 == "root") print $1}' /etc/passwd
root
#
# awk -F: '{if ($1 == "root") {print $1;print $6}}' /etc/passwd
root
/root
#

if (条件1)
动作1
else
动作2
# awk -F: '{if ($1 == "root"){print $1}else print $6}' /etc/passwd
# awk -F: '{if ($1 == "root") print $1;else print $6}' /etc/passwd
上面两个命令是等价的,要么用分号隔开,表示第一个动作体的结束,要么将动作体用大括号定位范围

if (条件 1)
动作1
else if(条件 2)
动作2
else if(条件 3)
动作3
else
动作4
# awk -F: '{if ($1 == "root") print $1;else if ($1 == "seker") print $6;else if ($1 == "zorro") print $7;else print NR}' /etc/passwd
root
2
3
...
33
/home/seker
/bin/bash
36

 

条件 ? 动作1 : 动作2
expr?action1:action2
# awk -F: 'var=($3 >= 500)?$1:"system_user" {print $1"\t"$3"\t"var}' /etc/passwd
# awk -F: '{print ($3>500?$1:$2)}' /etc/passwd

 

练习
将系统用户按UID分组标记 0 admin; 1-499 sysuser; 500+ users
awk -F: '{if($3==0) print $1"\t"$3"\t""admin";else if($3>=1&&$3<500) print $1,$3,"sysuser";else print $1,$3,"user"}' /etc/passwd

 

输出样式
%s是字符类型,%d数值类型
printf默认是不输出换行的所以要加\n
10和7是偏移量
默认是右对齐,所有加个- 就是左对齐,就是把不足的位数用空格填充
注意:格式与输出列之间要有逗号
# awk -F: '{printf "%-10s %-10d %s\n",$1,$3,$7}' /etc/passwd

 


读前处理和读后处理
# awk -F: 'BEGIN{i=1} {i++} END {print i}' /etc/passwd
47
#
# awk -F: 'BEGIN {print NR,NF}' /etc/passwd
0 0
#
# awk -F: 'END {print NR,NF}' /etc/passwd
46 7
#
练习
找出普通用户的用户名并统计数量
# awk -F: 'BEGIN{i=0} $3 >= 500 {print $1;i++} END {print i}' /etc/passwd
计算UID相加的总和;计算GID相加的总和
# awk -F: 'BEGIN{i=0}{sum+=$3;i++}END{print i;print sum}' /etc/passwd
# awk -F: 'BEGIN{i=0}{sum+=$3;gsum+=$4;i++}END{print i;print sum;print gsum}' /etc/passwd
计算VSZ和RSS各自的和 并以M单位显示
# ps aux | awk 'BEGIN{i=0}NR>=2{sum+=$5;i++}END{print sum/1024"M"}'
# ps aux | awk 'BEGIN{i=0}NR>=2{vsum+=$5;rsum+=$6;i++}END{print vsum/1024"M";print rsum/1024"M";print i}'
循环语句
while(条件) {
动作
条件运算
}
# awk -F: '{while($3<3) {print $3,$1;$3++}}' /etc/passwd
0 root
1 root
2 root
1 bin
2 bin
2 daemon
#
BEGIN块可以独立使用,不需要引入文件
# awk 'BEGIN{i=1;while(i<100) {print i;i++}}'
练习
打印100以内的偶数
# awk 'BEGIN{i=1;while(i<100) {if (i%2==0) print i;i++}}'

x=1
do {
动作1
x++
} while (x<5)
# awk 'BEGIN{i=5;do{print i;i++}while(i<10)}'
# awk 'BEGIN{i=5;do{print i;i++}while(i<1)}'

 

for(预置;条件;递增) {
动作
}
# awk 'BEGIN {for (x=1;x<=4;x++) print x }'
1
2
3
4
#
# awk 'BEGIN{for (i=1;i<=4;i++) {for (j=1;j<=4;j++) print i,j}}'

 


练习
使用嵌套的for循环,打印100-999之间的数,个十百位分别用一个for来打印
# awk 'BEGIN{OFS="";for (i=1;i<=9;i++) {for (j=0;j<=9;j++) {for (n=0;n<=9;n++) print i,j,n}}}'
打印乘法口诀表
# cat 99.sh
#!/bin/bash
awk 'BEGIN{
for(i=1;i<10;i++)
{
for(j=1;j<=i;j++)
printf "%d*%d=%d ",j,i,j*i
print
}

 

}'
#

 

打印金字塔
# cat jin.sh
#!/bin/bash
awk 'BEGIN{
num=5
for(i=1;i<=num;i++)
{
for (n=1;n<=num-i;n++)
printf "%s"," "
for (j=1;j<=2*i-1;j++)
printf "%s","*"
print
}
}'
#

 

逆序输出每个字段
达到这样既可
/bin/bash
/root
root
0
0
x
root

 


# awk -F: '{for (x=NF;x>0;x--) print $x}' /etc/passwd

 

继续解决上一个试做题的格式问题
# awk -F: '/bash$/{for (x=NF;x>0;x--) printf "%-13s",$x;printf "\n"}' /etc/passwd

 

跳转语句
break 跳出循环
# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) break;print x }}'
1
2

continue 在达到循环底部之前终止当前循环 从新开始下一次循环
# awk 'BEGIN {for(x=1;x<5;x++) {if (x==3) continue;print x }}'
1
2
4

 

next 读入下一行 同时返回脚本顶部 这样可以避免对当前行执行其他操作
# awk -F: 'NR > 5 {next} {print $1} END {print NR}' /etc/passwd
root
bin
daemon
adm
lp
46
#
exit 使读取动作终止 并将控制移动到END,如果没有END则终止脚本
# awk -F: 'NR > 5 {exit} {print $1} END {print NR}' /etc/passwd
root
bin
daemon
adm
lp
6
#

 

数组
自定义数组
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";print ary[1],ary[2]}'
seker zorro
#
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";for(i in ary) print ary[i]}'
seker
zorro
#
删除一个元素 对元素给空值并不能清除这个元素 要想清除一个元素需要使用delete ary[idx]
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";ary[3]="blues";ary[2]="";for(i in ary) print ary[i]}'
seker

 

blues
# awk 'BEGIN {ary[1]="seker";ary[2]="zorro";ary[3]="blues";delete ary[2];for(i in ary) print ary[i]}'
seker
blues
#

 

循环产生数组和取出数组
# awk 'BEGIN{n=5;for (i=1;i<=n;i++) ary[i]=i+100;for(m in ary) print m,ary[m]}'
4 104
5 105
1 101
2 102
3 103
#

# awk -F: '{ary[NR]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
7 shutdown
8 halt
9 mail
# awk -F: '{ary[$3]=$1} END {for(i in ary) print i,ary[i]}' /etc/passwd
10 uucp
11 operator
12 games
13 gopher
14 ftp
32 rpc
37 rpm

 

ARGV 命令行中参数数组
# awk '{for (i in ARGV) {print i,ARGV[i]}}' /etc/passwd /etc/fstab
0 awk
1 /etc/passwd
2 /etc/fstab
#### i 为下标; ARGV[i] 下标为i的值
练习
统计每种shell被使用的次数

 


函数

 

算术函数 int
[root@stu254 ~]# awk 'BEGIN {print int(3.9415)}'
3
[root@stu254 ~]#

 


随机数函数 rand() srand()
rand() 取值 0 > r < 1 之间 默认的种子是系统时间 精确到秒
srand()取值 0 > r < 1 之间 可以指定种子来影响rand()取值数 默认是系统时间 精确到秒

 

[root@stu254 ~]# awk 'BEGIN {srand(222);print int(rand()*100000000)}'
90204196
[root@stu254 ~]#

 

字符串函数
substr(s,x[,y])
返回字符串s中从位置x起至y的子串,如果没有给出y,则从x开始到结束.
[root@stu254 ~]# awk 'BEGIN {x="abcdefxyz";print substr(x,4,3)}'
def
[root@stu254 ~]#

 

大写小写
sprintf() 本身并不能打印,做格式转换,将数字转换成ASCII字符
# awk 'BEGIN {for(i=97;i<=122;++i) print tolower(toupper(sprintf("%c",i)))}'

 

字符串长度
length() 如果没有给定字符串则使用$0
[root@stu254 ~]# awk 'BEGIN {print length("abcdefxyz")}'
9

 

gsub(/abc/,"ABC",x) 全局字符串替换
从x中用匹配的abc正则替换成ABC
[root@stu254 ~]# awk 'BEGIN {x="xyzabcxyzabcxyz";gsub(/abc/,"ABC",x);print x}'
xyzABCxyzABCxyz
[root@stu254 ~]# sub 第一次的替换
[root@stu254 ~]# awk 'BEGIN {x="xyzabcxyzabcxyz";sub(/abc/,"ABC",x);print x}'
xyzABCxyzabcxyz
[root@stu254 ~]#

 

gensub(r, s, h [, t]) Search the target string t for matches of the reg-
ular expression r. If h is a string beginning
with g or G, then replace all matches of r with s.
Otherwise, h is a number indicating which match of
r to replace. If t is not supplied, $0 is used
instead.
gensub(正则,替换,范围,目标串)
[root@tch254 ~]# awk 'BEGIN{print gensub("zorro","AAAA","2","seker zorro zorro seker")}'
seker zorro AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | sed 's/zorro/AAAA/2'
seker zorro AAAA seker
[root@tch254 ~]#
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","g");print}'
seker AAAA AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","2");print}'
seker zorro AAAA seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","h");print}'
seker AAAA zorro seker
[root@tch254 ~]# echo seker zorro zorro seker | awk '{$0=gensub("zorro","AAAA","1");print}'
seker AAAA zorro seker
[root@tch254 ~]#

 


系统函数
getline

 

交互输入
[root@stu254 ~]# awk -F: 'BEGIN {printf "Enter Number: ";getline ;for(i=1;i<=$0;i++) print i}'
Enter Number: 3
1
2
3
[root@stu254 ~]#

 

将输入赋值给变量
[root@stu254 ~]# awk -F: 'BEGIN {printf "Enter Number: ";getline NUM;for(i=1;i<=NUM;i++) print i}'
Enter Number: 3
1
2
3
[root@stu254 ~]#

 

从文件中读入
[root@tch254 ~]# awk -F: 'BEGIN {getline < "/etc/passwd" ; print $3"\t"$1}'
0 root
[root@tch254 ~]#

 

#awk -F: 'BEGIN {while (getline < "/etc/passwd" > 0) print $3"\t"$1}'

 

getline < "/etc/passwd" 从文件中读入,每次读取一行,默认情况下读取的次数等于awk自身引入文件的行数
也可以放到for中来控制读取的次数
> 0 测试读取的返回值,成功返回1,失败返回-1,0文件末尾

 

从命令输出中输入
[root@stu254 ~]# awk 'BEGIN {"uname -a"|getline ;print $3}'
2.6.18-53.el5
[root@stu254 ~]#

 

 

 


system(command)
系统命令要用""引起来
[root@stu254 ~]# rm -rf abc/
[root@stu254 ~]# awk 'BEGIN {if(system("mkdir abc") != 0 ) print "ERR"}'
[root@stu254 ~]# awk 'BEGIN {if(system("mkdir abc") != 0 ) print "ERR"}'
mkdir: 无法创建目录 “abc”: 文件已存在
ERR
[root@stu254 ~]#
[root@tch254 ~]# awk 'BEGIN {if(system("mkdir abc 2>/dev/null") != 0 ) print "ERR"}'
ERR
[root@tch254 ~]#

 

awk脚本的介绍 -f 与 #!/bin/awk -f

 

使用awk添加系统用户
[root@mail ~]# cat useradd.awk
#!/bin/awk -f

 

{
system("useradd "$1";echo "$2"|passwd --stdin "$1)
}
[root@mail ~]# cat username
myname 1234
[root@mail ~]#
[root@mail ~]# ./useradd.awk ./username
Changing password for user myname.
passwd: all authentication tokens updated successfully.
[root@mail ~]#

 

1.使用:或/符号做分隔符,将字段逆序输出/etc/passwd文件的每行2.
# awk -F: 'NR < 11 {print $3,$1}' /etc/passwd > name.txt
# awk -F: 'NR < 11 {print $3,$6}' /etc/passwd > home.txt
# join name.txt home.txt 
观察两个文件,以及join命令输出,用awk引入name.txt,home.txt两个文件,模拟joni命令的输出3.统计/etc/passwd中每种shell的被使用人数
输出格式:
counts    shell
1    
1    /bin/sync
4    /bin/bash
31    /sbin/nologin
1    /sbin/halt
1    /sbin/shutdown4.统计ps中RSZ,VSS各自总和
输出格式:
ps MEM statistic
VSZ_SUM : 164.277M
RSS_SUM : 47.8555M5.计算/etc/passwd中所有用户的UID平均数,以及GID平均数.
输出格式:
UID and GID AVG
UID-AVG : 1750.72
GID_AVG : 17546.
根据uid值给用户分等级 Admin system users
输出格式:LEVEL  NAMEAdmin    root
sysuser    bin
users    sekeradmin_count: N sys_user_count: N users_count: N 7.
分别用GREP,SED,AWK将ifconfig中匹配到eth1的网卡所有信息打印出来.8.
SHELL实现批量建立多个文件,将文件拓展名加上.txt,再加上.doc,再把中间的.txt去掉
9.
AWK脚本实现间隔五行打印表头
[root@mail ~]# ./awk_print.sh /etc/passwd
Username  Uid    
root      0      
bin       1      
daemon    2      
adm       3      
lp        4      Username  Uid    
shutdown  6      
halt      7      
mail      8      
news      9      
uucp      10     10.用$RANDOM产生100个随机数,交给AWK产生数组,在数组内部排序,最后输出.(禁止用sort命令)11. 建立 aa.txt 文本
# cat aa.txt 
aaa/bbb/ccc
ddd/eee/fff
ggg/hhh/iii
aaa/bbb/ccc/aaa/bbb/ccc/ddd/eee
# 用AWK或SED输出如下格式
ccc aaa/bbb/
fff ddd/eee/
iii ggg/hhh/
eee aaa/bbb/ccc/aaa/bbb/ccc/ddd/12. 建立 a.txt b.txt 文件
[root@tch254 ~]# cat a.txt 
1    a
2    b
3    c
4    d
5    e
6    f
7    g
[root@tch254 ~]# cat b.txt 
5    ABC
3    DEF
4    XYZ
[root@tch254 ~]# 使用AWK处理两个文件输出如下结果
e ABC
c DEF
d XYZ
[root@tch254 ~]# 
awk选做作业

五 其他补充

11111111111
2222222222
333333333
4444444444
55555555555
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
99999999999999
99999999999999
99999999999999
99999999999999
99999999999999
99999999999999
99999999999999
aaaaaaaaaa
6666666666
777777777777
888888888888
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
99999999999999
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
test文件内容

 

[root@MiWiFi-R3-srv ~]# cat test |sort |uniq #排序去重
11111111111
2222222222
333333333
4444444444
55555555555
6666666666
777777777777
888888888888
99999999999999
aaaaaaaaaa


[root@MiWiFi-R3-srv ~]# cat /etc/passwd |cut -d: -f2

[root@MiWiFi-R3-srv ~]# find / -size +2M -type f -name \*.txt

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

转载于:https://www.cnblogs.com/linhaifeng/p/6596660.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/572636.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机二级办公软件高级应用难不难,计算机二级office难吗 考试内容是什么

相信很多的在校大学生或者已经开始工作的小伙伴都会有考虑过要考国二MsOffice高级应用考试&#xff0c;那么&#xff0c;计算机二级office难吗&#xff1f;考试内容是什么&#xff1f;计算机二级office难吗许多考生基础差&#xff0c;考生缺乏备考计划&#xff0c;超过70%的考生…

vue.js指令v-model实现方法

原文链接&#xff1a;http://www.jb51.net/article/99097.htm V-MODEL 是VUE 的一个指令&#xff0c;在input 控件上使用时&#xff0c;可以实现双向绑定。 通过看文档&#xff0c;发现他不过是一个语法糖。 实际是通过下面的代码来实现的&#xff1a; <% page language&quo…

山西财大华商学院计算机系,山西财经大学华商学院

山西财经大学华商学院&#xff0c;位于山西省太原市&#xff0c;是经国家教育部正式批准设立&#xff0c;由山西财经大学在2002年举办的一所全日制本科院校&#xff0c;学院紧邻山西财经大学主校区&#xff0c;目前在校学生4500余人。山西财经大学是新中国成立后建校最早的财经…

sed 解释正则表达式

以/etc/passwd文件为模板 1&#xff0c;删除文件每行的第一个字符。 2&#xff0c;删除文件每行的第二个字符。 3&#xff0c;删除文件每行的最后一个字符。 4&#xff0c;删除文件每行的倒数第二个字符。 5&#xff0c;删除文件每行的第二个单词。 转载于:https://www.cnblogs…

计算机usb无法读取u盘启动,U盘中毒后造成U盘启动盘制作失败usb无法识别的解决办法...

我们想用U盘作为装系统的工具&#xff0c;必须先保证U盘的安全才能作为U盘启动盘使用&#xff0c;如果U盘一旦损坏&#xff0c;将造成USB无法识别&#xff0c;装系统也就无从下手&#xff0c;下面先讲下U盘中毒后造成U盘损坏usb无法识别的情况&#xff1a;1、识别U盘速度变得缓…

在windows下codeblocks中配置pthread库

转自&#xff1a;http://blog.csdn.net/u013172314/article/details/50846198 如果添加方法不正确&#xff0c;可能会出现pthread_create’未定义的引用&#xff0c;所以下面我讲一下正确的配置方法。 首先介绍一下我的安装平台和需要下载的工具包&#xff1a; win7 64位&#…

吕帅 计算机学院,刘磊-吉林大学计算机科学与技术学院

在《Journal of Systems and Software》、《Pattern Recognition》、《计算机学报》、《软件学报》等国内外期刊和会议上累计发表学术论文180余篇&#xff0c;其中&#xff1a;SCI检索论文40余篇、EI检索论文100余篇。主要代表性学术论文(SCI检索学术论文、国内权威期刊论文)&a…

河南科技大学计算机基础题库,河南科技大学大学计算机基础Excel基本操作选择题汇总...

Excel基本操作1、在Excel工作表的单元格中&#xff0c;如要输入数字字符串100083(邮政编码)时&#xff0c;应输入____C___。A) 100083 B) "100083" C) 100083 D) 1000832、在单元格B1中输入数值2&#xff0c;B2中输入数值3.5&#xff0c;选定单元格区域 B1:B5&#x…

[Android-Appium]: 安卓自动化测试: 环境准备

安卓自动化测试&#xff1a;环境的准备&#xff1a; 在做安卓自动化测试之前&#xff0c;需要在你的电脑上做如下环境的准备&#xff0c; 我用的是 Appium做的自动化测试。 安装Appium server&#xff0c; 安装路径&#xff1a;http://appium.io/ https://bitbucket.org/app…

计算机考研8,计算机考研每日一练:第八天

平衡二叉树实现原理平衡二叉树构建的基本思想就是在构建二叉排序树的过程中&#xff0c;每当插入一个结点时&#xff0c;先检查是否因插入而破坏了树的平衡性&#xff0c;若是&#xff0c;则找出最小不平衡子树。在保持二叉排序树特性的前提下&#xff0c;调整最小不平衡子树中…

Python全栈开发:web框架们

Python的WEB框架 Bottle Bottle是一个快速、简洁、轻量级的基于WSIG的微型Web框架&#xff0c;此框架只由一个 .py 文件&#xff0c;除了Python的标准库外&#xff0c;其不依赖任何其他模块。 1234pip install bottleeasy_install bottleapt-get install python-bottlewget htt…

jsoup 去除html标签,如何使用jsoup取消注释html标签

Kai Sternad..7对的,这是可能的.以下是解决此问题的一种方法:查找所有评论节点对于每个注释,提取数据属性在当前注释节点之后插入包含数据的新节点删除注释节点看看这段代码:public class UncommentComments {public static void main(String... args) {String htmlIn "&…

软件测试实验二

1.百度搜索seleniumIDE&#xff0c;进入官网http://www.seleniumhq.org/download/下载区下载软件 2.使用seleniumIDE录制脚本&#xff0c;打开IDE&#xff0c;录制脚本&#xff0c;并测试脚本 3.导出脚本&#xff0c;完成实验 转载于:https://www.cnblogs.com/wyp-run/p/661974…

计算机在管理会计应用中的作用,信息化在管理会计中的作用

信息化在管理会计中的作用在管理会计的日常工作中&#xff0c;需要进行大量的数据收集整理工作&#xff0c;会出现漏算错算等情况&#xff0c;加强管理会计软件的创新和研发&#xff0c;从而推进企业会计电算化。摘要:较比以往&#xff0c;信息技术不断发展&#xff0c;在人们的…

基于鸢尾花数据集的逻辑回归分类实践

基于鸢尾花数据集的逻辑回归分类实践 重要知识点 逻辑回归 原理简介&#xff1a; Logistic回归虽然名字里带“回归”&#xff0c;但是它实际上是一种分类方法&#xff0c;主要用于两分类问题&#xff08;即输出只有两种&#xff0c;分别代表两个类别&#xff09;&#xff0c…

solr 的 field, copyfield ,dynamic field

Field: Field就是一个字段&#xff0c;定义一个Field很简单&#xff1a; [html] view plaincopy <field name"price" type"sfloat" indexed"true" stored"true"/> 基本上属性也和FieldType类似&#xff0c;他的属性会覆盖掉Fie…

校办研修之计算机培训简报,“2018校本研修培训”第二期学习简报

原标题&#xff1a;“2018校本研修培训”第二期学习简报校训校风&#xff1a;博教风学风&#xff1a;学习提升&#xff0c;共约成长洛阳市第二十六中学2018年校本研修培训学习简报(第二期)素材收集&#xff1a;数学组、物理组、生物组制 作&#xff1a;郭志伟、张志刚时 间&…

struts2中配置文件的调用顺序

1、default.properties 该文件保存在 struts2-core-2.3.7.jar 中 org.apache.struts2中 2、struts-default.xml 该文件保存在 struts2-core-2.3.7.jar 3、struts-plugin.xml 该文件保存在struts-Xxx-2.3.7.jar&#xff08;struts2的插件jar包中&#xff09; 4、struts.xml 该…

计算机教学研究与实践课题研究报告,(高职计算机教学改革与实践研究课题中期报告.doc...

(高职计算机教学改革与实践研究课题中期报告《高职计算机教学改革与实践研究》课题中期报告我院自开展本课题研究工作以来&#xff0c;紧紧围绕“项目教学法”教学的应用问题&#xff0c;积极主动地开展专题研究和教改实验&#xff0c;研究探索新的技术环境下教育教学的新模式和…

Python之路 day1 基础1 变量 for while 用户输入

一、 Python介绍 python的创始人为吉多范罗苏姆&#xff08;Guido van Rossum&#xff09;。1989年的圣诞节期间&#xff0c;吉多范罗苏姆为了在阿姆斯特丹打发时间&#xff0c;决心开发一个新的脚本解释程序&#xff0c;作为ABC语言的一种继承。 最新的TIOBE排行榜&#xff…