第二十五天笔记
grep 命令实践
grep 是 Linux 系统中最重要的命令之一,其功能是从文本文件或管道数据流中筛选匹配的行及数
据
grep 命令选项
模式选择和解释选项
-E 选项
支持扩展正则表达式,相当于 egrep 命令
bash
[han@shell ~]$ cat words | grep -E '(dog){3}'
# 或者
[han@shell ~]$ cat words | egrep '(dog){3}'
dogdogdog
dogdogdogdog
-e 选项
使用多个 -e 选项匹配多个 PATTERNS
bash
[han@shell ~]$ cat words | grep -e 'cat' -e 'dog'
# 或者
[han@shell ~]$ cat words | egrep 'cat|dog'
cat
category
acat
concatenate
dog
dogdog
dogdogdog
dogdogdogdog
hello cat
- i 选项
忽略大小写匹配。
bash
[han@shell ~]$ cat words | grep -i 'cBt'
cbt
-w 选项
匹配整个单词
bash
[han@shell ~]$ cat words | grep -w 'cat'
# 或者
[han@shell ~]$ cat words | grep '\bcat\b'
cat
hello cat
-x 选项
匹配整行
bash
[han@shell ~]$ cat words | grep -x 'cat'
# 或者
[han@shell ~]$ cat words | grep '^cat$'
cat
输出控制选项
-v 选项
反向匹配,显示与 PATTERNS 不匹配的项目。
bash
[han@shell ~]$ cat words | egrep -v '^d|^c'
acat
hello cat
# 不看注释行和空白行
[han@shell ~]$ egrep -v '^ *#|^$' /etc/profile
-m 选项
控制最大匹配数目,匹配特定次数后停止匹配
bash
[han@shell ~]$ cat words | grep 'dog'
dog
dogdog
dogdogdog
dogdogdogdog
[han@shell ~]$ cat words | grep -m2 'dog'
dog
dogdog
-c 选项
显示匹配到项目的数量
bash
[han@shell ~]$ cat words | grep -c 'dog'
4
-b 选项
显示匹配项目的字节偏移量
bash
[han@shell ~]$ head -5 words
cat
category
acat
concatenate
dog
[han@shell ~]$ cat words | grep -b 'cat'
0:cat
4:category
13:acat
18:concatenate
109:hello cat
-n 选项
显示匹配项目的行号。
bash
[han@shell ~]$ cat words | grep -n 'cat'
1:cat
2:category
3:acat
4:concatenate
19:hello cat
-o 选项
只显示匹配到的内容,行中其他内容不显示。
bash
[han@shell ~]$ cat words | egrep '(dog){3}'
dogdogdog
dogdogdogdog
[han@shell ~]$ cat words | egrep -o '(dog){3}'
dogdogdog
dogdogdog
-q 选项
不显示任何正常输出。一般用于脚本判定文件中是否包含特定内容
通过特殊变量 $? 查看是否匹配到内容
bash
# 找到的情况
[han@shell ~]$ cat words | egrep -q '(dog){3}'
[han@shell ~]$ echo $?
0
# 找不到的情况
[han@shell ~]$ cat words | egrep -q '(dog){3}asdfasfdasf'
[han@shell ~]$ echo $?
1
查找文件选项
-r -R 选项
- -r ,递归匹配目录。
- -R ,递归匹配目录,跟随软链接。
bash
[han@shell ~]$ grep -r '^SELINUX=' -s /etc
/etc/selinux/config:SELINUX=disabled
h 和 -H 选项
- -h ,不显示匹配项目所在文件的文件名。
- -H ,显示匹配项目所在文件的文件名,默认情况使用该选项
bash
[han@shell ~]$ grep -r '^SELINUX=' -s -l /etc
/etc/selinux/config
[han@shell ~]$ grep -r '^SELINUX=' -s -L /etc | tail -5
/etc/gdm/PostLogin/Default.sample
/etc/gdm/PostSession/Default
/etc/gdm/PreSession/Default
/etc/gdm/custom.conf
/etc/nfs.conf
输出内容控制选项
-B 选项
显示匹配项目本身,以及前多少行
bash
[han@shell ~]$ ip addr | grep '10.1.8.88' -B2
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
state UP group default qlen 1000
link/ether 00:0c:29:2b:c8:7a brd ff:ff:ff:ff:ff:ff
inet 10.1.8.88/24 brd 10.1.8.255 scope global noprefixroute ens32
-A 选项
显示匹配项目本身,以及后多少行。
bash
[han@shell ~]$ ip addr |grep 'ens32:' -A2
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
state UP group default qlen 1000
link/ether 00:0c:29:2b:c8:7a brd ff:ff:ff:ff:ff:ff
inet 10.1.8.88/24 brd 10.1.8.255 scope global noprefixroute ens32
C 选项
显示匹配项目本身,以及前后多少行。
bash
[han@shell ~]$ ip addr |grep '10.1.8.88' -C2
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
state UP group default qlen 1000
link/ether 00:0c:29:2b:c8:7a brd ff:ff:ff:ff:ff:ff
inet 10.1.8.88/24 brd 10.1.8.255 scope global noprefixroute ens32
valid_lft forever preferred_lft forever
inet6 fe80::5882:62aa:161b:c9c1/64 scope link tentative
noprefixroute dadfailed
sed 使用手册
sed 介绍
sed,英文全称 stream editor ,是一种非交互式的流编辑器,能够实现对文本非交互式的处理,功能很强大。
sed 与 awk 并称为 Linux/Unix 世界的两大王牌文字处理器:
- sed 侧重点是替换。
- awk 侧重点是分割和重新合成。
Linux操作文本的三大利器,简称三剑客,分别是:
- grep:擅长过滤。
- sed:擅长修改文本。
- awk:擅长格式化输出
sed 工作流程
bash
读取行 -> 执行 -> 显示 -> 读取行 -> 执行 -> 显示 -> .... -> 读取行 -> 执行
-> 显示
sed 命令语法
bash
sed [option] [sed-command] [input-file]
- sed 命令。
-
option\] 命令行选项,用于改变 sed 的工作流程。
-
input-file\] 输入数据,如果不指定,则默认从标准输入中读取。
bash
[han@shell ~]$ cat data.txt
I am studing sed
I am www.twle.cn
I am a no-work-men
I am so handsome
[han@shell ~]$ sed '' data.txt
I am studing sed
I am www.twle.cn
I am a no-work-men
I am so handsome
**示例2:**从标准输入中读取数据
bash
[han@shell ~]$ sed ''
# 输入hello world,并回车
hello world
# 输出hello world
hello world
# 按ctrl+d推出
-e 选项
从命令行读取sed命令,我们需要将 sed 命令使用单引号 ( '' ) 引起来。
bash
# 打印data.txt文件内容
[han@shell ~]$ sed -e '' data.txt
# 如果只有一个命令, -e选项可以省略
[han@shell ~]$ sed '' data.txt
# -e 选项可以多次使用, 1d是作用是删除第一行
[han@shell ~]$ sed -e '1d' -e '2d' -e '5d' data.txt
I am a no-work-men
I am so handsome
# 因为不存在第五行,所以也就没删除的效果
# 使用分号( ;)分开多个命令
[han@shell ~]$ sed -e '1d;2d;5d' data.txt
I am a no-work-men
I am so handsome
-n 选项
如果指定了该选项,那么模式空间数据将不会自动打印,需要明确指明打印才会输出记录
bash
# 以下命令没有任何输出
[han@shell ~]$ sed -n '' data.txt
# 打印第一行记录
[han@shell ~]$ sed -n '1p' data.txt
I am studing sed
sed 正则表达式
sed 行寻址
作用
通过行寻址匹配要处理的输入流。
示例文件
bash
[han@shell ~]$ echo 'This is 1
This is 2
This is 3
This is 4
This is 5 ' > test
示例1: 打印所有行
bash
# 打印所有行
[han@shell ~]$ cat test | sed ''
# 输出结果
This is 1
This is 2
This is 3
This is 4
This is 5
# sed 默认打印模式缓冲区中所有内容。
# 等效于
[han@shell ~]$ cat test | sed -n 'p'
# -n 关闭sed打印模式缓冲区中所有内容。
# p命令,明确打印输出模式缓冲区中所有内容。
示例2: 打印特定行
bash
# 打印第1行
[han@shell ~]$ cat test | sed -n '1p'
# 输出结果
This is 1
# 打印第最后一行
[han@shell ~]$ cat test | sed -n '$p'
# 输出结果
This is 5
示例3: 打印第1行到3行
bash
[han@shell ~]$ cat test | sed -n '1,3p'
# 输出结果
This is 1
This is 2
This is 3
示例4: 打印第3行到最后一行
bash
[han@shell ~]$ cat test | sed -n '3,$p'
# 输出结果
This is 3
This is 4
This is 5
示例5: 连续输出,打印第2行以及后续两行
bash
[han@shell ~]$ cat test | sed -n '2,+2p'
# 输出结果
This is 2
This is 3
This is 4
示例6: 隔行输出,打印第1行以及后续隔2行输出
bash
[han@shell ~]$ cat test | sed -n '1~2p'
# 输出结果
This is 1
This is 3
This is 5
sed 模式寻址
sed 除了可以从行号来选择行, s还支持模式查找指定的行。
- 模式 可以是一个普通的字符串或者一个正则表达式。
- 模式 的语法和行寻址的语法类似,只是把行号换成了 模式 匹配
示例文件
bash
[han@shell ~]$ cat << 'EOF' > ~/test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/home/ftp:/bin/false
&nobody:$:99:99:nobody:/:/bin/false
zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
http:x:33:33::/srv/http:/bin/false
dbus:x:81:81:System message bus:/:/bin/false
hal:x:82:82:HAL daemon:/:/bin/false
mysql:x:89:89::/var/lib/mysql:/bin/false
aaa:x:1001:1001::/home/aaa:/bin/bash
ba:x:1002:1002::/home/zhangy:/bin/bash
test:x:1003:1003::/home/test:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
EOF
示例1: 打印含有字符串zhang的行
bash
[han@shell ~]$ cat test | sed -n '/zhang/p'
zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
ba:x:1002:1002::/home/zhangy:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
示例2: 打印root开头的行到zhang开头的行
bash
[han@shell ~]$ cat test | sed -n '/^root/,/^mail/p'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
示例3: 打印root开头的行到第三行
bash
[han@shell ~]$ cat test | sed -n '/^root/,3p'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
示例4: 打印root开头的行到最后一行
bash
[han@shell ~]$ cat test | sed -n '/^root/,$p'
sed 命令
打印
作用
- p,打印模式空间所有记录。
- P,打印模式空间第一行记录。
bash
[han@shell ~]$ echo 'This is 1
This is 2
This is 3' | sed -n '1{N;p}'
# 输出结果
This is 1
This is 2
[han@shell ~]$ echo 'This is 1
This is 2
This is 3' | sed -n '1{N;P}'
# 输出结果
This is 1
读取下一行
bash
[han@shell ~]$ echo 'This is 1
This is 2
This is 3
This is 4
This is 5' | sed -n 'n;p'
# 输出内容
This is 2
This is 4
替换
示例1: 把test文件中的root替换成tankzhang
bash
[han@shell ~]$ sed 's/root/tankzhang/' test|grep tankzhang
tankzhang:x:0:0:root:/root:/bin/bash
示例2: 把test文件中的root全部替换成tankzhang。 字母g是global的缩写。
bash
[han@shell ~]$ sed 's/root/tankzhang/g' test |grep tankzhang
tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例3: 加了 -n 和 p 后表示只打印那些发生替换的行(部分替换)
bash
[han@shell ~]$ sed -n 's/root/tankzhang/p' test
tankzhang:x:0:0:root:/root:/bin/bash
示例4: 加了 -n 和 pg 后表示只打印那些发生替换的行(全部替换)
bash
[han@shell ~]$ sed -n 's/root/tankzhang/gp' test
tankzhang:x:0:0:tankzhang:/tankzhang:/bin/bash
示例5: 在第二行到第八行之间,替换以zhang开头的行,用ying来替换,并显示替换的行
bash
[han@shell ~]$ sed -ne '2,8s/^zhang/ying/gp' test
yingy:x:1000:100:,,,:/home/zhangy:/bin/bash
示例6: 从以zhang开头的行开始,到匹配Po的行结束,在他们之间进行替换
[han@shell ~]$ sed -ne '/^zhang/,/Po/ s/zhang/ying/gp' test
yingy:x:1000:100:,,,:/home/yingy:/bin/bash
ba:x:1002:1002::/home/yingy:/bin/bash
@yingying:*:1004:1004::/home/test:/bin/bash
示例7: 自定义替换分隔符为 # 。 默认是\。
bash
[han@shell ~]$ sed -n 's#root#hello#gp' test
hello:x:0:0:hello:/hello:/bin/bash
其他替换
bash
[han@shell ~]$ cat test1.txt
my my my my my
my my my my my
my my my my my
#替换每行第3个my
[han@shell ~]$ sed "s/my/your/3" test1.txt
my my your my my
my my your my my
my my your my my
#只替换第3行的第1个my
[han@shell ~]$ sed "3s/my/your/1" test1.txt
my my my my my
my my my my my
your my my my my
#只替换每行的第3个及以后的my
[han@shell ~]$ sed 's/my/your/3g' test1.txt
my my your your your
my my your your your
my my your your your
分隔符;和-e选项
需要执行多个sed处理命令时, 用分号分开 ,或者使用 -e 选项。
示例:
- 在第2行到第8行之间,替换以zhang开头的行,用ying来替换
- 在第5行到第10行之间,用goodbay来替换dbus,并显示替换的行
bash
[han@shell ~]$ cat test | sed -n
'2,8s/^zhang/ying/gp;5,10s#dbus#goodbay#gp'
yingy:x:1000:100:,,,:/home/zhangy:/bin/bash
goodbay:x:81:81:System message bus:/:/bin/false
[han@shell ~]$ cat test | sed -ne '2,8s/zhang/ying/gp' -ne
'5,10s#dbus#goodbay#gp'
yingy:x:1000:100:,,,:/home/yingy:/bin/bash
goodbay:x:81:81:System message bus:/:/bin/false
插入
a 在匹配行下面插入新行
将要插入的东西,插入到匹配行的下面
bash
[han@shell ~]$ sed '/root/a====aaaa====' test
root:x:0:0:root:/root:/bin/bash
====aaaa====
bin:x:1:1:bin:/bin:/bin/false
......
i 在匹配行上面插入新行
bash
[han@shell ~]$ sed '/root/i====iiii====' test
====iiii====
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
......
删除
作用
- d,删除模式空间所有记录。
- D,删除模式空间第一行记录。
示例1: 删除1, 14行
bash
[han@shell ~]$ sed -e '1,14d' test
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
示例2: 删除4以后的行,包括第4行,把$当成最大行数就行了
bash
[han@shell ~]$ sed -e '4,$d' test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
示例3: 删除包括false的行,或者包括bash的行,别忘了加 \
bash
[han@shell ~]$ sed -e '/\(false\|bash\)/d' test
policykit:x:102:1005:Po
示例4: 删除从匹配root的行,到匹配以test开头的行,中间的行
bash
[han@shell ~]$ sed -e '/root/,/^test/d' test
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
awk 使用手册
awk 介绍
awk 是一个强大的文本分析工具。
awk 更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等。
awk 内置变量
NF 变量
变量 NF 是 Number of Fields 的缩写,用于表示当前行分割出来的字段/列数量。
下面的命令输出了当前每一行有被分割出了多少个字段
bash
[han@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk '{ print $0
"\t",NF }'
运行以上代码,输出结果如下:
bash
一 二 2
一 二 三 3
一 二 三 四 4
变量 NF 还可以用于条件判断。
例如,下面的命令输出了哪些字段/列大于 2 的行
bash
[han@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk 'NF > 2'
运行以上代码,输出结果如下:
bash
一 二 三
一 二 三 四
NR 变量
变量 NR 是 Number of Record 的缩写,用于表示当前行的行号,也就是处理到第几行。行编号从 1 开始。
下面的代码,用于在每一行数据的前面输出当前的行号
bash
[han@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk '{ print
NR". "$0 }'
运行以上代码,输出结果如下:
bash
1. 一 二
2. 一 二 三
3. 一 二 三 四
变量 NR 还可以用于条件判断,例如下面的命令用于输出行号小于 3 的行,也就是第一第二行。
[han@shell ~]$ echo -e "一 二\n一 二 三\n一 二 三 四" | awk 'NR < 3'
运行以上代码,输出结果如下:
bash
一 二
一 二 三
$N
对于 AWK 来说,默认的分割符是空白符号,包括 "\t" 和空格 " "。当 AWK 使用分割符对每一行进行分割后,会对每一列/字段进行编号:
- 1 2 $3 ... ,分别代表第1列,第2列,第3列...
- $0 ,代表一整行。
示例1:
bash
[han@shell ~]$ head -n1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
[han@shell ~]$ head -n1 /etc/passwd |awk '{ print $0 }'
root:x:0:0:root:/root:/bin/bash
[han@shell ~]$ head -n1 /etc/passwd |awk -F : '{ print $1" "$6 }'
root /root
示例2: 统计 /usr/share/doc 目录下文件 size 最大的前10个,并显示文件size
bash
[han@shell ~]$ sudo find /usr/share/doc -type f -ls | awk '{print
$7,$11}' | sort -nr | head
919864 /usr/share/doc/lame-libs/ChangeLog
860207 /usr/share/doc/rsyslog/ChangeLog
815954 /usr/share/doc/bash/bashref.html
749664 /usr/share/doc/systemd/NEWS
619537 /usr/share/doc/gtk3/NEWS
561462 /usr/share/doc/grub2-common/grub.html
541159 /usr/share/doc/sane-backends/ChangeLog
515412 /usr/share/doc/glib2/NEWS
452027 /usr/share/doc/openssh/ChangeLog
446555 /usr/share/doc/xdg-desktop-portal/portal-docs.html
# 如何让文件的单位使用human size显示?
[han@shell ~]$ sudo find /usr/share/doc -type f -ls | awk '{print
$7,$11}' | sort -nr | head |awk '{print $2}' | xargs ls -lh
-rw-r--r--. 1 root root 797K Nov 19 2020
/usr/share/doc/bash/bashref.html
-rw-r--r--. 1 root root 504K Aug 19 2021 /usr/share/doc/glib2/NEWS
-rw-r--r--. 1 root root 549K Mar 11 2022 /usr/share/doc/grub2-
common/grub.html
-rw-r--r--. 1 root root 606K Dec 21 2021 /usr/share/doc/gtk3/NEWS
-rw-r--r--. 1 root root 899K Oct 14 2017 /usr/share/doc/lamelibs/ChangeLog
-rw-r--r--. 1 root root 442K Aug 20 2021
/usr/share/doc/openssh/ChangeLog
-rw-r--r--. 1 root root 841K Feb 15 2021
/usr/share/doc/rsyslog/ChangeLog
-rw-r--r--. 1 root root 529K Feb 14 2021 /usr/share/doc/sanebackends/ChangeLog
-rw-r--r--. 1 root root 733K Jan 18 2022 /usr/share/doc/systemd/NEWS
-rw-r--r--. 1 root root 437K Feb 9 2022 /usr/share/doc/xdg-desktopportal/portal-docs.html