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%的考生…

sed 解释正则表达式

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

在windows下codeblocks中配置pthread库

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

[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…

软件测试实验二

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…

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

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

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

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

20155302 2016-2017-2 《Java程序设计》第六周学习总结

20155302 2016-2017-2 《Java程序设计》第6周学习总结 教材学习内容总结 Java中的流分为两种&#xff0c;一种是字节流&#xff0c;另一种是字符流&#xff0c;分别由四个抽象类来表示&#xff08;每种流包括输入和输出两种所以一共四个&#xff09;:InputStream&#xff0c;Ou…

找不到tgp饥荒专用服务器,饥荒tgp版专用服务器搭建指南_游侠网

《饥荒》很多玩家购买了tgp版&#xff0c;对于服务器的搭建还不熟悉。下面小编带来《饥荒》tgp版专用服务器搭建指南&#xff0c;一起来看吧。1.创建以下文件夹\\(我的)文档\Klei\\DoNotStarveTogetherRail\MyDediServer\\(我的)文档\Klei\\DoNotStarveTogetherRail\MyDediServ…

elementui源码_Element UI 终于还是来啦

昨天&#xff0c; Element Plus for Vue 3.0 Beta 版本正式发布了&#xff01;对&#xff0c;就是那个被外界传言不再维护的Element UI&#xff01;Element Plus for Vue 3.0 是一个使用 TypeScript Composition API 重构的全新项目。官方团队几乎重写了每一行 代码&#xff0…

复地邮箱服务器地址,打印服务器设置方法

现在很多人会使用打印机&#xff0c;打印机可以帮助我们打印一些资料&#xff0c;但是很多人之前可能没有使用过打印机&#xff0c;因此自己购买了之后发现不会使用&#xff0c;不会设置&#xff0c;今天就为您介绍一下打印服务器安装设置&#xff0c;希望对您有帮助。打印服务…

腐蚀rust研究台抽奖_中石化青岛安工院专家分享延迟焦化装置的腐蚀风险分析!...

延迟焦化装置的腐蚀风险分析李贵军&#xff0c;单广斌(中国石化青岛安全工程研究院)主要内容&#xff1a;对某延迟焦化装置的腐蚀情况进行了描述&#xff0c;根据装置的流程特点、操作条件、设备选材和结构&#xff0c;对装置的腐蚀类型和腐蚀原因进行了分析&#xff0c;提出了…

目标检测如何计算召回率_计算机视觉目标检测的框架与过程

计算机视觉个人接触机器视觉的时间不长&#xff0c;对于机器学习在目标检测的大体的框架和过程有了一个初步的了解&#xff0c;不知道对不对&#xff0c;如有错误&#xff0c;请各位大牛不吝指点。目标的检测大体框架&#xff1a;计算机视觉目标检测分为以下几个步骤&#xff1…

修改wap游戏服务器,修改wap游戏服务器

修改wap游戏服务器 内容精选换一换部署游戏应用前&#xff0c;您需要准备硬件以及华为云的环境&#xff0c;主要包括以下内容&#xff1a;硬件环境&#xff1a;您需要准备一台带有显卡的Windows机器&#xff0c;硬盘至少20G&#xff0c;用于运行游戏客户端。若您不需要运行游戏…

e5cc温控仪通讯参数设定_自动化工程师:施耐德 PLC常见两种编程通讯控制实例,收好不谢...

1、第一种是采用 UNTLW1协议进行联机编程&#xff1a;参数设置与通讯配置检查&#xff1a;用 Premium的专用编程电缆“TSXPCX3030-C(USB接口&#xff0c;有专门的驱动)”通过调试机与CPU上的TER口进行连接&#xff0c;连接好后&#xff0c;点击某单栏里的“PLC(P)”菜单&#x…

flask登录验证用ajax,基于 Ajax 请求的 Flask-Login 认证

index.htmlexample.py## index.htmlindex.html test login by Leetao未点击var load_msg function () {$.get(/hello?api_keytest_login,function(data){$(#test_login)[0].innerText data})}example.pyfrom flask import Flask, request, jsonify, render_templatefrom fla…