一、正则使用
正则字符 | 作用 |
---|---|
^str | 查找在行首的字符串str |
str$ | 查找在行尾的字符串str |
. | 除换行符\n外的任何单个字符 |
\ | 转义符 |
* | 匹配前面的字符或子表达式 0-N次 |
+ | 重复前面的字符或子表达式 1-N次 |
? | 重复前面的字符或子表达式 0-1次 |
[list] | 匹配中括号里的字符【注:q[wert] 表示的字符可以是qw、qe、qr、qt,即只要包含括号里的单个字符都匹配】 |
[^list] | 与[list]相反,表示不包含括号里的字符 |
str1|str2 | 或,满足左右两个字符或两个表达式的字符串 |
{n,m} | 1. {n}:匹配前面一个字符或子表达式n次【必须n次,不能多不能少】 |
2.{n,}:匹配前面一个字符或子表达式至少n次 | |
3.{n,m}:匹配…n到m次 | |
() | 标记一个子表达式的开始和结束 |
[A-Z]和[a-z] | 分别表示所有大写字母和小写字母 |
[0-9] | 所有数字 |
\s | 匹配任何空白符,包括空格、制表符、换页符等 |
\S | 任何非空白字符 |
?= | **exp1(?=exp2):**匹配exp2表达式前面的exp1表达式匹配的字符 |
?<= | (?<=exp2)exp1 匹配exp2表达式后面的exp1表达式所匹配的字符 |
?! | exp1(?!exp2) 匹配后面不是exp2表达式的exp1 |
?<! | (?<!exp2)exp1 匹配前面不是exp2的exp1 |
示例文本:
[root@localhost ~]# cat regex_txt
lala
haha
heihei
yoyo
示例:
-
查找行首为l的:
[root@localhost ~]# grep -n '^l' regex_txt 1:lala
-
查找行尾为o的:
[root@localhost ~]# grep -n 'o$' regex_txt 4:yoyo
-
查找符合axa的字符,即两个a中间必须有一个字符的字符:
[root@localhost ~]# grep -n 'a.a' regex_txt 1:lala 2:haha
已练习,不想列了 太懒了
二、sed工具
sed也是管道命令,可处理标准输入。可对数据进行替换、删除、新增和选取特定行功能。
语法:sed [选项] [操作]
选项:
-n: 只列出sed处理的那些行
-f: 后跟filename,可将sed操作写入到文件,通过-f执行
-r: 使用扩展正则语法(默认支持基础正则)
-i: 直接修改读取的文件内容,非仅仅输出到屏幕
操作:
[n1,n2] oper
n1和n2表示要操作的行数,oper为具体的操作行为,分为以下几点:
-
a
新增,接新增的字符【新增到下一行】
-
c
替换change。替换n1-n2间的行为指定内容
-
d
删除。删除指定的[n1,n2]行
-
i
插入。与a相同,但插入到当前的前一行
-
p
打印。通常与 sed -n 搭配使用
-
s
替换。可搭配正则
示例:
[root@localhost ~]# cat test.txt
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
有以上一个文本。
2.1 删除
删除指定行数
# 删除/etc/passwd 3-6行
[root@localhost ~]# cat -n test.txt | sed '3,6d'
1 a
2 b
7 g
8 h
9 i
10 j
11 k
12 l
13 m
14 n
15 o
16 p
17 q
# 删除3行以后
[root@localhost ~]# cat -n test.txt | sed '3,$d'
1 a
2 b
# 删除第3行
[root@localhost ~]# cat -n test.txt | sed '3d'
1 a
2 b
4 d
5 e
6 f
7 g
8 h
9 i
10 j
11 k
12 l
13 m
14 n
15 o
16 p
17 q
其中,3行以后用3,$d
表示,$
表示最后一行。
2.2 新增
分别在第二行后和第二行前加上 love u
:
[root@localhost ~]# cat -n test.txt | sed '2a love u'
1 a
2 b
love u
3 c
4 d
5 e
6 f
7 g
8 h
[root@localhost ~]# cat -n test.txt | sed '2i love u'
1 a
love u
2 b
3 c
4 d
5 e
6 f
7 g
8 h
# 新增多行
[root@localhost ~]# cat -n test.txt | sed '2i love u\
> haha'
1 a
love u
haha
2 b
3 c
....
2.3 替换
替换3到6行的内容为:love u
[root@localhost ~]# cat -n test.txt | sed '3,6c love u'
1 a
2 b
love u
7 g
8 h
9 i
10 j
....
2.4 打印
截取3,6行打印出来:
[root@localhost ~]# cat -n test.txt | sed -n '3,6p'
3 c
4 d
5 e
6 f
一定要加 -n 啊,不然就会额外打印出其他所有数据:
[root@localhost ~]# cat -n test.txt | sed '3,6p'
1 a
2 b
3 c
3 c
4 d
4 d
5 e
5 e
6 f
6 f
7 g
.....
2.5 直接替换指定字符
刚刚的 c 操作是替换指定行,那如果我只想替换指定的字符怎么办?就可以用 s 操作,它更像是查询->替换。
语法:
`sed ‘s/替换的字符/新字符/g’,当然,替换的字符可以使用正则进行匹配
将c替换为lala:
[root@localhost ~]# cat -n test.txt | sed 's/c/lala/g'
1 a
2 b
3 lala
4 d
5 e
6 f
7 g
8 h
9 i
10 j
2.6 直接修改原文件
使用-i就可以直接修改原文件:
a修改问heihei:
[root@localhost ~]# sed -i 's/a/heihei/g' test.txt
[root@localhost ~]# cat test.txt
heihei
b
c
d
e
f
g
h
三、awk
awk倾向于将一行分成多个字段进行处理,一行内默认的字段分隔符为空格或TAB,适合处理小文本。
awk '条件类型1{操作1} 条件类型2{操作2}' filename
先看一个简单的例子:
打印last中的第1列和第2列
[root@localhost ~]# last | awk '{print $1 "\t" $2}'
root pts/0
root pts/0
root pts/0
root pts/1
root pts/0
reboot system
root tty1
root pts/1
一下就出来了,而之前用cut命令,按照空格分割,会因无法确定有多少个空格而无法准确的取到第2列值。awk由于默认按照空格或TAB分割,自动将一行拆分成多个字段,我们想打印哪个字段,就直接通过print n 就 可 以 , n就可以, n就可以,n就代表第n个字段,n从1开始。$0表示一整行数据
3.1 内置变量
-
NF
每行的字段数
-
NR
当前awk处理的第几行
-
FS
当前输入字段分割字符,默认空格
-
RS
输入记录分隔符 默认换行符,即每行作为一个单位进行处理,每行处理的分隔符为FS
-
OFS
输出字段分隔符,默认空格
-
ORS
输出记录分隔符,默认换行符
[root@localhost ~]# cat test.txt
heihei hehe
b wo ai ni
c yo yo n n n
d
e
f
g
以上文本。
非变量要用双引号引起来
[root@localhost ~]# cat test.txt | awk '{print "当前行:"NR",字段数:"NF",分隔符:"FS}'
当前行:1,字段数:2,分隔符:
当前行:2,字段数:4,分隔符:
当前行:3,字段数:6,分隔符:
当前行:4,字段数:1,分隔符:
当前行:5,字段数:1,分隔符:
当前行:6,字段数:1,分隔符:
当前行:7,字段数:1,分隔符:
3.2 逻辑运算
包括:
>
<
>=
<=
==
!=
对/etc/passwd 按 冒号进行分割,找出第3列小于10的行,然后打印出第1和第3列:
[root@localhost ~]# cat /etc/passwd | awk '{FS=":"} $3<10 {print $1 "\t" $3}'
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
但是,这里虽然指定了分隔符,但是只能作用在第2行和以后,第一行还是默认空格分割,如果想要第一行也被作用,需要使用BEGIN关键字:
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3<10 {print $1 "\t" $3}'
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
第一行就列出来了。
同样还有END关键字
-
BEGIN
awk会在读取任何输入行前执行
BEGIN
中指定的动作 -
END
awk会在其退出前执行
END
指定的动作[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3>10 {print $1 "\t" $3} END {print $1}' operator 11 games 12 ftp 14 nobody 99 systemd-network 192 dbus 81 polkitd 999 sshd 74 postfix 89 wangmaolin 1000 wangmaolin
在最后的时候打印出第一个变量
示例:
有如下文件:
[root@localhost ~]# cat cal.txt
col1 col2 col3
1 2 3
4 5 6
7 8 9
计算每列的和放到第4列:
[root@localhost ~]cat cal.txt | awk 'NR==1 {printf "%5s %5s %5s %5s\n", $1,$2,$3,"sum"}\
NR>=2 {printf "%5d %5d %5d %5d\n",$1,$2,$3,$1+$2+$3}'
col1 col2 col3 sum
1 2 3 6
4 5 6 15
7 8 9 24
指定输出分隔符:
[root@localhost ~]# cat cal.txt | awk 'BEGIN{OFS="---"} {print $1,$2,$3}'
col1---col2---col3
1---2---3
4---5---6
7---8---9
3.3 数组和循环
awk的数组看作python的字典,索引非索引,而是可理解为key,指定的key存放对应的value,key唯一,无序,使用for遍历时,是遍历的key,通过arr[key]可访问对应的值。
[root@localhost ~]# awk 'BEGIN {arr[1]=2
arr["a"] = 3
arr["haha"] = "heihei"
for(key in arr)
{
print arr[key]
}
}'
#结果:
3
heihei
2
删除元素也和python一样,delete arr[key]
[root@localhost ~]# awk 'BEGIN {arr[1]=2
arr["a"] = 3
arr["haha"] = "heihei"
for(item in arr)
{
print arr[item]
}
delete arr["a"]
print arr["a"]
}'
# 结果
3
heihei
2
# 打印空白,说明删除了
3.4 通过文件调用awk 并传参
其他的,awk也支持标准的流程运算,函数等,因此我们可以把它看作一个 脚本,也因此,我们可以把awk命令直接写入文件,通过调用文件的方式执行awk操作。
awk -f awk脚本文件名 [赋值变量] 数据文件
[root@localhost ~]# cat awk_script
{print $n name}
# 调用脚本,并给变量赋值
[root@localhost ~]# awk -f awk_script n=2 name="test" cal.txt
col2test
2test
5test
8test
更多用法:
http://c.biancheng.net/view/4097.html