grep、cut、sed、awk

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 脚本参数说明

脚本参数由匹配处理两个部分组成

  • 匹配用来筛选满足规定的行
    • 匹配条件可以直接指定特定的行
    • 匹配条件还支持正则,即满足正则条件的行
    • 没有匹配条件,则默认针对所有行进行操作
  • 处理则是针对于筛选出来的行进行增删改等操作
命令功能描述
aadd新增,a的后面可以接字串,在下一行出现
cchange更改, 更改匹配行的内容
ddelete删除, 删除匹配的内容
iinsert插入, 向匹配行前插入内容
pprint打印, 打印出匹配的内容,通常与-n选项和用
ssubstitute替换, 替换掉匹配的内容
=用来打印被匹配的行的行号
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支持队列中系统环境变量的使用
FILENAMEawk浏览的文件名
FNR各个文件的当前行号
FS设置输入域分隔符,等价于命令行 -F选项
NFnumber of field, 根据分隔符分割后的列数
NRnumber 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) 参数
选项说明
-nnumber,依照数值的大小排序
-rreverse, 以相反的顺序来排序
-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
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值