1. grep
1.1 格式
grep [otions] pattern filename
1.2 option常用参数
-A 8
: after 显示匹配行后8行-B 5
: before 显示匹配行前5行-C 5
:context 显示匹配行上下5行-E
: pattern可以使用扩展正则表达式-i
:不区分大小写-n
: 打印行号-o
: only matching 只输出匹配的内容。不加这个参数会把整行内容输出-m 10
: max-matches 最多匹配10个后停止-r
:递归搜索目录--color
: 将匹配的字符串用颜色显示出来
# 在dir1文件夹下查找所有good字符串
grep -rn good dir1
2. cut
cut命令逐行读入文本,然后按列划分字段并进行提取、输出等操作。
cut -c 提取范围 [file ...]
cut -f 提取范围 [-d delim] [file ...]
options参数说明
选项参数 | 功能 |
---|---|
-f 提取范围 | 列号,获取第几列 |
-d 自定义分隔符 | 自定义分隔符,默认 为制表符。 |
-c 提取范围 | 以字符为单位进行分割 |
提取范围说明
提取范围 | 说明 |
---|---|
n | 提取指定第n列或第n个字符数据 |
n- | 提取指定第n列或第n个字符和其后面所有 数据 |
n-m | 提取指定第n列或第n个字符到第m列或第m个字符之间 的所有数据 |
-m | 提取指定第m列或第m个字符前面所有数据 |
n1,n2,… | 提取第 n1,n2,.. 这些列或者字符 的数据 |
cat > cut1.txt <<-EOF
AA hello 11 XX
BB world 22 XXX
CC Shell 33 XXXX
DD it 44 XXXXXXX
EOF
# 提取文件中第一列数据
cut -d " " -f 1 cut1.txt
#提取文件中第一列,第三列, 枚举查找
cut -d " " -f 1,3 cut1.txt
cut -d " " -f 2-5 cut1.txt
cut -d " " -f 2- cut1.txt
cut -d " " -f -2 cut1.txt
# 提取文件中每一行的前三个字符
cut -c 1-3 cut1.txt
cut的作用
一个强大文本处理工具,它可以将文本按列进行划分的文本处理。cut命令逐行读入文本,然后按列划分字段并进行提取、输出等操作。
cut切割提取列
cut 文件或数据 -d 分隔符切割 -f 提取第X列
cut切割提取字符
cut 文件或数据 -c 提取字符范围
3. sed
set: (stream editor) 非交互流式文本编辑器
- 流式,一次处理一行内容,将这行放入缓存,然后对这行处理,处理完将内容再发送到终端
- 先按行匹配,然后可以对匹配的行进行增删改查等操作
- 支持按行,按字段,按正则匹配文本内容
3.1 使用格式
sed [选项参数] [模式匹配/sed程序命令] [文件名]
sed [OPTION]... {script} [input-file]...
模式匹配
: sed会读取每一行数据到模式空间中, 之后判断当前行是否符合模式匹配要求,符合要求就会执行sed程序命令, 否则不会执行sed程序命令;如果不写匹配模式,那么每一行都会执行sed程序命令
3.2 选项参数说明
选项参数 | 功能 |
---|---|
-e | 直接在指令列模式上进行sed的动作编辑。它告诉sed将下一个参数解释为一个sed指令,只有当命令行上给出多个sed指令时才需要使用-e选项;一行命令语句可以执行多条sed命令 |
-i | 直接对内容进行修改,不加-i时默认只是预览,不会对文件做实际修改 |
-f | 后跟保存了sed指令的文件 |
-n | 取消默认输出,sed默认会输出所有文本内容,使用-n参数后只显示处理过的行 |
-E | 使用扩展正则表达式,默认情况sed只识别基本正则表达式 * |
3.3 脚本参数说明
脚本参数由匹配
和处理
两个部分组成
- 匹配用来筛选满足规定的行
- 匹配条件可以
直接指定特定的行
- 匹配条件还支持正则,
即满足正则条件的行
- 没有匹配条件,则默认针对所有行进行操作
- 匹配条件可以
- 处理则是针对于筛选出来的行进行增删改等操作
命令 | 功能描述 |
---|---|
a | add新增,a的后面可以接字串,在下一行出现 |
c | change更改, 更改匹配行的内容 |
d | delete删除, 删除匹配的内容 |
i | insert插入, 向匹配行前插入内容 |
p | print打印, 打印出匹配的内容,通常与-n选项和用 |
s | substitute替换, 替换掉匹配的内容 |
= | 用来打印被匹配的行的行号 |
n | 读取下一行,遇到n时会自动跳入下一行 |
补充:
- -n :取消默认输出,默认输出为处理后的文本应该长什么样子。 加了-n只会打印新增的行,匹配的行和未匹配的行都不会再打印了
- 匹配:
查询符合条件的数据
- 处理:
对数据的增删改
- p : 将
匹配
的内容输出- 默认情况下会将所有内容输出,只加p后会再多打印一遍匹配的内容。
特殊符号
命令 | 功能描述 |
---|---|
! | 就像一个sed命令,放在限制条件后面, 对指定行以外的所有行应用命令(取反) |
{sed命令1;sed命令2} | 多个命令操作同一个的行 |
# 准备数据
cat > sed.txt <<-EOF
hello hello
word
123
hello
hello world
EOF
针对明确行号的行进行处理
-
第三行前插入一行who are you
sed '3iwho are you' sed.txt
-
删除第二行数据
sed '2d' sed.txt
-
删除第一行到第三行
sed '1,3d' sed.txt
-
删除最后一行 (PS:需要注意的是最后一行用
$
表示)
sed '$d' sed.txt
-
在最后一行后插入一行hello
sed '$ahello' sed.txt
-
在最后一行前插入一行hello
sed '$ihello' sed.txt
-
删除第1、4行数据
sed '1d;4d' sed.txt
-
删除第1至3行以外的所有行
sed '1,3!d' sed.txt
-
打印第1至3行以外的所有行
sed -n '1,3!p' sed.txt
-
替换第一行成hello
sed '1chello' sed.txt
-
替换最后一行为hello
sed '$chello' sed.txt
-
将第1行里面的所有hello替换成world
sed '1s/hello/world/g'
针对正则匹配上的行进行处理
- 在所有中包含hello的行后
插入一行
world
sed '/hello/aworld' sed.txt
- 替换所有包含hello的行为world
sed '/hello/cworld' sed.txt
- 将所有包含hello的行中的所有hello改成world
sed '/hello/s/hello/world/g' sed.txt
- 将所有包含world的行中的所有hello改成world
sed '/world/s/hello/world/g' sed.txt
- 删除不包含hello或world的行
sed ‘/hello|world/!d’ sed.txt
针对所有的行进行处理
- 将每行中的第一个hello替换成good
sed 's/hello/good/' sed.txt
- 将每行中所有的hello替换成good
sed 's/hello/good/g' sed.txt
- 在所有行的行尾添加test
sed 's/$/test/' sed.txt
- 在每行行首添加注释
sed 's/^/#/' sed.txt
综合应用
-
从匹配到hello的行开始,到最后一行进行删除
sed ‘/hello/,$d’ sed.txt
-
删除匹配hello行及其后面一行
sed ‘/hello/,+1d’ sed.txt
-
-n 取消默认打印方式, p 将匹配行打印从出来
sed -n '/hello/p' sed.txt
-
将每一行行尾添加world,同时删除第3行
sed -e 's/$/world/' -e '5d' sed.txt
sed '{s/$/结束/;3d}' a.txt
3.4 缓存区数据交换
- sed处理文件是逐行处理的, 即读取一行处理一行,输出一行;
- sed把文件读出来每一行存放的空间叫模式空间, 会在该空间中对读到的内容做相应处理;
- sed还有一个额外的空间即暂存空间, 暂存空间刚开始里边只有个空行
- sed可使用相应的命令从模式空间往暂存空间放入内容或从暂存空间取内容放入模式空间
命令 | 含义 |
---|---|
h | 将模式空间里面的内容复制到暂存空间缓存区(覆盖方式) |
H | 将模式空间里面的内容复制到暂存空间缓存区(追加方式) |
g | 将暂存空间里面的内容复制到模式空间缓存区(覆盖方式) |
G | 将暂存空间里面的内容复制到模式空间缓存区(追加方式) |
x | 交换2个空间的内容 |
将模式空间第一行复制到暂存空间(覆盖方式),并将暂存空间的内容复制到模式空间中的最后一行(追加方式)
sed '1h;$G' sed.txt
# 1h 从模式空间中将第一行数据复制到暂存空间(覆盖方式)
# $G 将暂存空间中的内容复制到模式空间中最后一行(追加方式)
将模式空间第一行复制到暂存空间(覆盖方式)并删除, 最后将暂存空间的内容复制到模式空间中的最后一行(追加方式)
sed '1{h;d};$G' sed.txt
# 1{h;d}对模式空间中的第一行数据同时进行复制到暂存空间(覆盖方式)和删除模式空间中的第一行数据
将模式空间第一行复制到暂存空间(覆盖方式), 最后将暂存空间的内容复制到模式空间中替换从第2行开始到最后一行的每一行数据(覆盖方式)
sed '1h;2,$g' sed.txt
将前3行数据复制到暂存空间(追加方式), 之后将暂存空间的所有内容复制粘贴到模式空间最后一行(追加方式)
sed '1,3H;$G' sed.txt
每一行之后插入空行
sed G -i sed.txt
# G 每行后面添加一个空行
# -i 修改源文件
删除所有的空行
sed -i '/^$/d' sed.txt
4. awk
awk 是一个强大的文本分析工具
awk [options] 'pattern{action}' {filenames}
选项参数说明
选项参数 | 功能 |
---|---|
-F | 指定输入文件拆分分隔符 |
-v | 赋值一个用户定义变量 |
-f | 从脚本文件中读取awk命令 |
4.1 awk 内置变量
内置变量 | 含义 |
---|---|
ARGC | 命令行参数个数 |
ARGV | 命令行参数排列 |
ENVIRON | 支持队列中系统环境变量的使用 |
FILENAME | awk浏览的文件名 |
FNR | 各个文件的当前行号 |
FS | 设置输入域分隔符,等价于命令行 -F选项 |
NF | number of field, 根据分隔符分割后的列数 |
NR | number of records 当前记录数, 也就是行数 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 默认以换行为一条记录的结束,可以改成其他 |
RS | 控制记录分隔符 输入的时候以读到什么作为一行的结束 |
$n | $0 变量是指整条记录。$1 表示当前行的第一个域,$2 表示当前行的第二个域,…以此类推。 |
$NF | $NF是number finally,表示最后一列的信息,跟变量NF是有区别的,变量NF统计的是每行列的总数 |
cat > ps.txt <<-EOF
root 1906 0.0 0.0 107796 7124 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 1908 0.0 0.0 77044 8124 ? Ss 09:10 0:00 /lib/systemd/systemd --user
ljs 1909 0.0 0.0 262068 3244 ? S 09:10 0:00 (sd-pam)
ljs 2022 0.0 0.0 110224 6328 ? S 09:10 0:00 sshd: ljs@pts/8
root 2023 0.0 0.0 107796 7016 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 2024 0.0 0.0 24944 6124 pts/8 Ss 09:10 0:00 -bash
ljs 2110 0.0 0.0 110092 5372 ? S 09:10 0:00 sshd: ljs@notty
ljs 2111 0.0 0.0 13068 2128 ? Ss 09:10 0:00 /usr/lib/openssh/sftp-server
ljs 3529 0.4 0.3 2070344 409356 ? Ssl 4月12 25:18 mysqld
ljs 3557 0.5 0.3 2070064 410136 ? Ssl 4月12 28:25 mysqld
ljs 3565 0.4 0.3 2795156 434060 ? Ssl 4月12 25:59 mysqld
ljs 42475 0.0 0.0 41420 3776 pts/8 R+ 09:35 0:00 ps -aux
ljs 42476 0.0 0.0 16184 1040 pts/8 S+ 09:35 0:00 grep --color=auto ljs
EOF
# 输出第1,2,3列 ,用&拼接各列
awk '{print $1"&"$2"&"$3}' ps.txt
# 输出第1,2,3列 , 逗号表示用默认分隔符分割每列
awk '{print $1,$2,$3}' ps.txt
# 列前面加上一些前缀
awk '{print "第一列:"$1,"第二列:"$2}' ps.txt
# 输出每行所有信息
awk '{print $0}' ps.txt
# 匹配第五行,再处理
awk 'NR==5{print $0}' ps.txt
# 匹配2到6行
awk 'NR==2,NR==6{print $0}' ps.txt
# 给每行加上行号
awk '{print NR":"$0}' ps.txt
awk '{print NR,$0}' ps.txt
# 显示第一列,第二列,倒数第二列
awk '{print $1,$2,$(NF-1)}' ps.txt
4.2 分隔符
- 输入分隔符: 默认是空格(多个空格连在一起也算一个分隔符),变量名为FS(field separator)
- 输出分割符:output field separator
cat > pwd.txt <<-EOF
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
EOF
# 以:为输入分隔符
awk -F ":" '{print $1}' pwd.txt
awk -v FS=":" '{print $1}' pwd.txt
# 指定以#号为输出字段分隔符
awk -F ":" -v OFS="#" '{print $1,$2}' pwd.txt
# 以制表符为输出字段分隔符
awk -F ":" -v OFS="\t" '{print $1,$2}' pwd.txt
4.3 变量
- 内置变量:awk定义好的变量
- 自定义变量:自己定义的变量
cat > ps.txt <<-EOF
root 1906 0.0 0.0 107796 7124 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 1908 0.0 0.0 77044 8124 ? Ss 09:10 0:00 /lib/systemd/systemd --user
ljs 1909 0.0 0.0 262068 3244 ? S 09:10 0:00 (sd-pam)
ljs 2022 0.0 0.0 110224 6328 ? S 09:10 0:00 sshd: ljs@pts/8
root 2023 0.0 0.0 107796 7016 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 2024 0.0 0.0 24944 6124 pts/8 Ss 09:10 0:00 -bash
ljs 2110 0.0 0.0 110092 5372 ? S 09:10 0:00 sshd: ljs@notty
ljs 2111 0.0 0.0 13068 2128 ? Ss 09:10 0:00 /usr/lib/openssh/sftp-server
ljs 3529 0.4 0.3 2070344 409356 ? Ssl 4月12 25:18 mysqld
ljs 3557 0.5 0.3 2070064 410136 ? Ssl 4月12 28:25 mysqld
ljs 3565 0.4 0.3 2795156 434060 ? Ssl 4月12 25:59 mysqld
ljs 42475 0.0 0.0 41420 3776 pts/8 R+ 09:35 0:00 ps -aux
ljs 42476 0.0 0.0 16184 1040 pts/8 S+ 09:35 0:00 grep --color=auto ljs
EOF
# 每行添加文件名
awk '{print FILENAME,$0}' ps.txt
# BEGIN{前置动作}{动作}
awk 'BEGIN{print "执行动作前的行为"}{print $0}' ps.tx
# 取出参数
awk 'NR==1{print ARGC,ARGV[0],ARGV[1]}' ps.txt
# 设置一个自定义变量 BEGIN可以不指定文件
awk -v myname="zhangsan" 'BEGIN{print "我的名字是?",myname}'
# 引用系统变量
awk -v path=$PATH 'BEGIN{print path}'
4.4 格式化输出
cat > ps.txt <<-EOF
root 1906 0.0 0.0 107796 7124 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 1908 0.0 0.0 77044 8124 ? Ss 09:10 0:00 /lib/systemd/systemd --user
ljs 1909 0.0 0.0 262068 3244 ? S 09:10 0:00 (sd-pam)
ljs 2022 0.0 0.0 110224 6328 ? S 09:10 0:00 sshd: ljs@pts/8
root 2023 0.0 0.0 107796 7016 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 2024 0.0 0.0 24944 6124 pts/8 Ss 09:10 0:00 -bash
ljs 2110 0.0 0.0 110092 5372 ? S 09:10 0:00 sshd: ljs@notty
ljs 2111 0.0 0.0 13068 2128 ? Ss 09:10 0:00 /usr/lib/openssh/sftp-server
ljs 3529 0.4 0.3 2070344 409356 ? Ssl 4月12 25:18 mysqld
ljs 3557 0.5 0.3 2070064 410136 ? Ssl 4月12 28:25 mysqld
ljs 3565 0.4 0.3 2795156 434060 ? Ssl 4月12 25:59 mysqld
ljs 42475 0.0 0.0 41420 3776 pts/8 R+ 09:35 0:00 ps -aux
ljs 42476 0.0 0.0 16184 1040 pts/8 S+ 09:35 0:00 grep --color=auto ljs
EOF
# 格式化输出
awk '{printf "%s\n",$0}' ps.txt
awk 'BEGIN{printf "%d,%d,%d\n",1,2,3}'
awk '{printf "第一列:%s 第二列:%s 第三列:%s \n",$1,$2,$2}' ps.txt
# %-25 左对齐,长度为25
awk '{printf "%-25s\t %-25s\t %-25s \n",$1,$2,$3}' ps.txt
4.5 模式
awk是按照行处理文本
- BEGIN模式 : 表示处理文本前的要执行的操作
- END模式 : 表示处理完所有行之后的操作
- awk默认是按行处理文本,如果不指定任何模式(条件),则每行都进行处理
- 如果指定了模式,则只处理符合模式的行
cat > ps.txt <<-EOF
root 1906 0.0 0.0 107796 7124 ? Ss 09:10 0:00 sshd: ljs [priv]
ljs 1908 0.0 0.0 77044 8124 ? Ss 09:10 0:00 /lib/systemd/systemd --user
EOF
awk 'BEGIN{print "开始处理文本"}{print $0}END{print "处理文本完成"}' ps.txt
awk 'NR<4{print $0}' ps.txt
# 匹配正则
awk '/^r/{print $0}' ps.txt
# 找到以r开头和到l开头之间所有的用户
awk '/^r/,/^l/{print $0}' ps.txt
补充
# 拼接
echo "abc hello world 21" | awk -v str="" '{for(n=1;n<=NF;n++){ str=str$n} print str }'
# 运算
echo "2.1" | awk -v i=1 '{print $0+i}'
# 切割ip
ifconfig | awk '/broadcast/{print}' | awk -F " " '{print $2}'
5. sort
能够对文件内容进行排序,并将排序结果标准输出或重定向输出到指定文件
sort (options) 参数
选项 | 说明 |
---|---|
-n | number,依照数值的大小排序 |
-r | reverse, 以相反的顺序来排序 |
-t 分隔字符 | 设置排序时所用的分隔字符, 默认空格是分隔符 |
-k | 指定需要排序的列 |
-d | 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。 |
-f | 排序时,将小写字母视为大写字母 |
-b | 忽略每行前面开始出的空格字符 |
-o 输出文件 | 将排序后的结果存入指定的文件 |
-u | 意味着是唯一的(unique),输出的结果是去完重了的 |
-m | 将几个排序好的文件进行合并 |
5.1 常用示例
cat > sort.txt <<-EOF
张三 30
李四 95
播仔 85
播仔 85
播仔 86
AA 85
播妞 100
EOF
# 默认将每一行作为一个元素进行排序,以ascii码排序
sort sort.txt
# 以第二列按数值排序
sort -t " " -k2n,2 sort.txt
# 因为是按列,所以要指定列分隔符
# -n表示按数字排序,-k表示按那一列排序
sort -t " " -k2nr sort.txt
# 按第二行以数字排序,并按第1,2行去重。
sort -t " " -k2nr,2 -uk1,2 sort.txt
能够使用sort对字符串升序或降序排序
字符串升序:
sort -kstart,end 文件
字符串降序:
sort -kstartr,end 文件
能够使用sort 对数字升序或降序
数字升序:
sort -kstartn,end 文件
数字降序:
sort -kstartnr,end 文件
能够使用sort 对多列进行排序
sort -kstart[nr],end -kstart[nr],end ... 文件
6. 练习题
6.1 查文件中所有的空行行号
awk '/^$/{print NR}' file.txt
6.2 查询文件中某一列之和
awk '{sum+=$2}END{print "求和:",sum}' file.txt
6.3 检查文件是否存在
if [ -e /root/file.txt ]; then echo "文件存在"; else echo "文件不存在";fi
6.4 对每行都是数字的文件排序
sort -n file3.txt
6.5 在root目录下找出所有含123的文件名称
grep -r "123" /root | cut -d ":" -f 1 | sort -u
6.7 从某个文件中找出含有root的行
grep 'root' file.txt
6.7 从文件中找出以root开头的行
grep '^root' file.txt
6.8 找出以root或以ljs开头的行
grep -E '^(root|ljs)' file.txt
6.9 bin开头的行,且显示行号
grep -n "^bin" file.txt
6.10 找出不以root开头的行
grep -v "^root" file.txt
6.11 统计root出现的行数
grep -c "^root" file.txt
6.12 输出以root开始的行,最多输出两行
grep -m 2 '^root' file.txt
6.13 从指定的多个文件中查找root
grep "root" a.txt b.txt c.txt
6.14 查看指定文件列表中哪些文件包含root
grep -l "root" a.txt b.txt c.txt d.txt
6.15 查询不以root结尾的行
grep -n -v "root$" file.txt
6.16找出以两位数或三位数的行
grep -E "\<[0-9]{2,3}\>" file.txt
# <> 表示单词的边界。 需要转移。就是说匹配的是整个词,而不是词的部分
6.17 找出一个shell脚本中的所有函数名
grep -E "[a-zA-Z]+\(\)" file.sh
6.18 找出用户名和其shell解析器 名相同的记录
grep -E "^([^:]+\>).*\1$" /etc/passwd
6.19 将文件中的root替换成ljs(修改源文件)
sed -in 's/root/ljs/g' file.txt
6.20 将文件中root替换成ljs,并仅仅打印替换的结果
sed -n 's/root/ljs/gp' file.txt
6.21 将前10行以b开头的改成以c开头
sed '1,10s/^s/c/' file.txt
6.22 将前10行中以b开头的改成c,以m开头的改成M
sed -e '1,10s/^s/c/' -e 's/^m/M/' file.txt
6.23 只保留前五行
sed '6,$d' file.txt
6.24 删除以root开始到ftp之间的行
# 逗号表示范围
sed '/^root/,/^ftp/d' file.txt
6.25 将文件中以空格开头的行或空行添加注释符
sed -e 's/^ /#/g' -e 's/^$/#/g' file.txt
6.26 删除文件中的空白行和注释行
sed -e '/^#/d' -e '/^$/d' file.txt
sed '/^#/d;/^$/d' file.txt
6.27 将前三行内容行首添加@符号
sed -r '1,3s/(^.)/@\1/' file.txt
6.28 取出ip地址
ifconfig eno1 | sed -n '2s/^.*inet//;s/netmask.*//p'
6.29 在当前系统中打印所有的普通用户和家目录
# uid>1000的是普通用户
cat /etc/passwd | awk -F ":" '$3>=1000{print $1,"\t\t",$(NF-1)}'
6.30 给前5行添加# 号
awk 'NR<6{print "#",$0}' file.txt
6.31 以空格或者冒号作为列分隔符
awk -F "[ :]" '!/^$/{print $1,$2}' file.txt
6.32 找到所有第二列以d开头的内容
# $2~ 表示第二列进行正则匹配
awk '$2~/^d/{print $0}' file.txt