grep、sed、awk 命令

学习使用 grep、sed、awk 命令

正则表达式

匹配开头结尾

  • ^ 匹配开头 例子:^abc 匹配以abc开头的
  • $ 匹配结尾 例子:abc$ 匹配以abc结尾的
  • ^$ 匹配空

匹配单个字符

字符 功能
[] 匹配括号中的任意一个字符, 括号中加^[^]表示匹配非括号中字符任意一个
\d 匹配一个数字, 0-9
\D 匹配一个非数字
\s 匹配空白, 即空格,tab…
\S 匹配非空白
\w 匹配一个单词字符, a-z, A-Z, 0-9, _, 各国语言的字
\W 匹配一个非单词字符
. 匹配任意一个字符(\n除外), 在DOTALL模式能匹配换行符

匹配多个字符

字符 功能
* 匹配前一个字符0或多次
+ 匹配前一个字符1或多次
? 匹配前一个字符0或1次
{m} 匹配前一个字符m次
{m, n} 匹配前一个字符m到n次
{m, } 匹配前一个字符m次以上
{, n} 最多匹配前一个字符n次

匹配分组

字符 功能
| 匹配左右任意一个表达式
() 将括号中的字符作为一个分组, 分组号从1开始

grep 命令

命令格式: grep [OPTIONS] PATTERN [FILE...]

用于过滤

  • 参数
1
2
3
4
5
6
7
8
9
10
-v: 选中没有匹配到的行
-E: 等同于`egrep`, 使支持拓展正则(`+ | () {} ? `)
-w: 精确匹配整个单词(过滤端口、进程的时候可以使用) --word-regexp
-i: 忽略大小写
-o: 仅输出匹配到的内容
-c: 输出匹配到的行数
-n: 显示行号
-An: 输出匹配到的内容及其后面的 n 行 --after-context
-Bn: 输出匹配到的内容及其前面的 n 行 --before-context
-Cn: 输出匹配到的内容及其前后面的 n 行 --context
  • 练习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 排除空行
grep -v '^$' /etc/profile
# 排除空行和'#'注释的行
grep -vE '^$|^#' /etc/profile
grep -vE '^($|#)' /etc/profile
# 输出文件中的单词
egrep -o '[a-Z]+' /etc/profile
# 匹配 hello | hallo
echo -e 'hello world\nhallo world' | grep -oE 'h(e|a)llo'

# ps + grep 查看进程是否运行 会匹配到此时运行的命令
ps -ef | grep dockerd
# 不会配自身
ps -ef | grep dockerd | grep -v grep
ps -ef | grep [d]ockerd # 此时运行的命令`grep [d]ockerd`, 二我们要找的是 dockerd

sed 命令

sed - stream editor for filtering and transforming text
命令格式:sed [OPTION]... {script-only-if-no-other-script} [input-file]
执行流程:按行读取内容到模式空间;匹配内容;执行增删改查操作

  • 参数:

-n: 取消模式空间默认输出
-r: 使其支持拓展正则

增删改查

1
2
3
4
5
6
7
8
p: 打印 
d: 删除 delete

c: 替换一行的内容
a: 指定行后面追加内容
i: 指定行前面插入内容

s: 替换 substitute
  • 查 p

注意: 只想输出指定内容时,一定要使用 -n 参数 (sed -n ...),取消模式空间默认输出

1
2
3
4
5
'np': 查第 n 行, 注意不是 /n/
'm,np': 查 m 到 n 行
'/regexp/p': 查 // 中表达式命中的行,类似grep
'/reg1/,/reg2/p': 查表达式1命中的行,到表达式2命中的行。注意:如果表达式2没有命中内容,则会一直查到文件结尾,并输出。
'n,/reg/p': 混用
  • 删 d
1
2
'nd':删除第n行
'$d':删除最后一行
  • 增 a,i
1
2
'ni str': 在第n行前插入 str\n
'na str': 在第n行后增加 str\n
  • 替换 s

格式:sed 's/old/new/g' 将 old(可以是表达式),匹配到的内容,替换成 new

  • /: 三个’/‘ 是分隔符,也可以用其它的符号表示, 如:’#’、‘@’
  • g: 全局替换,不加 ‘g’ 默认只替换每行第一个匹配到的内容
  • 例子
1
2
3
4
5
6
7
8
9
10
11
12
# 打印配置,排除空行、注释
sed -r '/^$|^#/d' /etc/profile # 默认不修改文件,打印删除后的内容
sed -nr '/^$|^#/!p' /etc/profile # '!' 取反, !p,表示不打印命中的内容

# 分组 \1, \2 ... 引用内容
echo hello world | sed -r 's/(.*) (.*)/\2 \1/' # 交换前后两个单词的位置

# 取所有网卡 ip
ip addr | sed -nr '/^ +inet .*/p' | sed -r 's#^.* (.*)/.*#\1#'
# 取eth0网卡 ip
ip addr show eth0 | sed -n '3p' | sed -r 's#^.* (.*)/.*#\1#'
ip addr show eth0 | sed -nr '3s#^.* (.*)/.*#\1#p' # 打印行、替换合并版

N/n 指令

N: 先读入第一行到pattern space,然后执行N命令,将第二行追加进pattern space。此时模式空间数据: ‘第一行内容\n第二行内容’
n: 先读入第一行到pattern space,然后执行n命令,用第二行覆盖pattern space。此时模式空间只有第二行内容

1
2
3
4
5
6
7
8
seq 1 10 | sed -n 'p;n'  # 奇数
seq 1 10 | sed -n 'n;p' # 偶数
# 合并奇偶行
seq 1 8 |sed -n 'N; s/\n//p'
12
34
56
78

awk 命令

gawk - pattern scanning and processing language

常用于过滤、统计计算、对比比较

命令格式:

  • awk [-W option] [-F value] [-v var=value] [–] ‘program text’ [file …]
  • awk [-W option] [-F value] [-v var=value] [-f program-file] [–] [file …]
  • awk 参数选项 ‘条件 {动作}’
    • 条件:比较符号、正则、范围表达式、特殊条件: BEGIN、END

置变量:

  • NR: Number of Record 记录号 即行号

  • NF: Number of Field 每行的字段数,即列数

  • FS: Field Separator 字段分割符,即列分隔符

  • OFS: Output Field Separator 输出字段分割符

参数:

  • -F: 指定列分隔符, 默认(空白符、连续的空白符)
  • -v: 设置变量
    • -vFS=::相当于 -F: 设置列分隔符分’:’
    • -vOFS=::设置输出分隔符分’:’

行与列

行:awk叫 record , 默认通过回车分割

列:awk叫 field(字段、域),默认通过空格分隔

  • 取行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 取第一行
awk 'NR==1' /etc/passwd
# 取三到五行
awk 'NR==1,NR==3' /etc/passwd
awk 'NR>=3 && NR<=5' /etc/passwd
# 取第三、第五行
awk 'NR==3 || NR==5' /etc/passwd

# 使用正则
# 取包含 sys 的行
awk '/sys/' /etc/passwd
# 取 s 开头的行
awk '/^s/' /etc/passwd
# 从包含 root 的行, 取到包含 sys 的行
awk '/root/,/sys/' /etc/passwd
  • 取列
    • $n: 引用第n列
    • $NF: 引用最后一列
    • $0: 引用整行,即 $1 $2 … $NF
    • $n~/reg/: 第n列满足表达式reg的
    • $n!~/reg/: 第n列满足表达式reg的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 取第一列和最后一列
awk -F: '{print $1,$NF}' /etc/passwd | column -t
# 取第一列和最后一列 输出使用 ':' 分割
awk -F: '{print $1":"$NF}' /etc/passwd
awk -F: -vOFS=: '{print $1,$NF}' /etc/passwd

# 取用户标识号大于100的
awk -F: '$3>=100{print $1,$3}' /etc/passwd | column -t
# 取可以登录的用户
awk -F: '$NF!~/nologin$/ {print $1}' /etc/passwd

# 取网卡IP地址
ip addr show eth0 | awk -F'[ /]+' 'NR==3 {print $3}'
ip addr | awk -F'[ /]+' '/inet / {print $3}'

特殊模式 BEGIN{}、END{}

模式 含义 应用场景
BEGIN{} 读取文件前执行 1. 进行简单计算,不涉及文件读取
2.处理文件前添加表头
3.定义awk变量(仅仅是定义变量,建议使用-v参数)
END{} 读取文件后执行 1. 进行统计
2.用来输出数组内容
1
2
3
4
5
6
7
8
9
10
11
12
# 累加求和
seq 100 | awk '{sum=sum+$1; print sum}'
seq 100 | awk '{sum=sum+$1} END{print sum}' # 只打印最后结果
awk 'BEGIN{for(i=1;i<=100;++i) {sum+=i} print(sum)}'
awk 'BEGIN{for(i=1;i<=100;++i) sum+=i; print(sum)}'

# 数组使用
awk 'BEGIN{arr[0]=1234;arr[1]="hello world"; for(i in arr) print i,arr[i]}'
# 统计历史命令输入的次数
history | awk '{arr[$2]++} END{for(i in arr) print i, arr[i]}' | sort -rnk2
# 输出单词长度大于等于5的
echo 'hello awk!' | awk -F'[ !]+' '{for(i=1;i<=NF;++i) if(length($i)>=5) print $i}'

tips: awk 字符串 需要使用 双引号, 否则会被当做变量标志符


 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×