Shell编程实战(四):文本处理三剑客

Ⅰ. 概述

  • grep是一个过滤器
  • sed是一个流编辑器
  • awk是报告生成器,对数据进行处理生成报告

Ⅱ. grep和egrep

egrep 是对 grep 的扩展

语法格式

  • 第一种形式:grep [option] [pattern] [file1, file2..]
  • 第二种形式:command | grep [option] [pattern]

grep参数

在这里插入图片描述

Ⅲ. sed

1. sed的工作模式

  • sed(Stream Editor),流编辑器,对标准输出或文件逐行进行处理

语法格式

  • 第一种:stdout | sed [option] "/pattern/command"stdout | sed [option] "command"
  • 第二种:sed [option] "/pattern/command" filesed [option] "command" file

2. sed的选项

在这里插入图片描述

例子

p命令之所以显示两次是因为第一次是显示原行信息,第二次是命令的结果

-n 的作用

-e 的作用

[flw@nlp2 ~]$ sed -n -e '/python/p' -e '/PYTHON/p' sed.txt
I love python
I love PYTHON
[flw@nlp2 ~]$

-f 的作用

[flw@nlp2 ~]$ cat edit.sed
/python/p
[flw@nlp2 ~]$ sed -n -f edit.sed sed.txt
I love python
[flw@nlp2 ~]$

-r 的作用

#  "|" 是扩展正则表达式


[flw@nlp2 ~]$ sed -n '/python|PYTHON/p' sed.txt      
[flw@nlp2 ~]$
[flw@nlp2 ~]$
[flw@nlp2 ~]$ sed -n -r '/PYTHON|python/p' sed.txt
I love python
I love PYTHON
[flw@nlp2 ~]$

-i 的作用

-i 最常用

[flw@nlp2 ~]$ sed -n 's/love/like/g;p' sed.txt
I like python
I like PYTHON
Hadoop is bigdataframe
[flw@nlp2 ~]$ cat sed.txt
I love python
I love PYTHON
Hadoop is bigdataframe
[flw@nlp2 ~]$
[flw@nlp2 ~]$ sed -i 's/love/like/g' sed.txt
[flw@nlp2 ~]$ cat sed.txt
I like python
I like PYTHON
Hadoop is bigdataframe
[flw@nlp2 ~]$

3. sed中的pattern详解

在这里插入图片描述

4. sed中的编辑命令详解

在这里插入图片描述

例子

a 行后追加

在这里插入图片描述

i 行前追加

在这里插入图片描述

r 命令

在这里插入图片描述

w 命令
[flw@nlp2 ~]$ sed -n '/\/bin\/bash/w /tmp/user.txt' passwd
s 修改
格式作用
s/pattern/string/查找符合pattern模式的字符串,将其替换为string。
同一行内,只替换第一个,等价于 s/pattern/string/1
s/pattern/string/g替换所有符合pattern模式的字符串
s/pattern/string/22: 同一行内,只替换前2个匹配的,剩下的不替换
s/pattern/string/2g2g: 同一行内,只替换从第2个开始往后的所有的匹配的字符串
s/pattern/string/igi: 表示匹配时忽略大小写

在这里插入图片描述

什么是反向引用

在这里插入图片描述

或者可以使用 sed -i 's/\(hermion.\)/\1s/g' leihou\1也可以表示反向引用,但是使用 \1 时前面必须加括号

\1& 的区别

在这里插入图片描述

seg 引用变量时的注意事项
  1. 匹配变量中如果存在变量,要使用双引号
    [flw@nlp2 ~]$ old_string="hermionc"
    [flw@nlp2 ~]$ new_string="hermione"
    [flw@nlp2 ~]$ sed -i "s/$old_string/$new_string/g" leihou
    
  2. sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号
    [flw@nlp2 ~]$ sed -i 's/'$old_string'/'$new_string'/g' leihou
    

5. 利用sed查询特定内容

例子

对mysql的配置文件 my.cnf 进行处理

#!/bin/bash

FILE_NAME=$PWD/my.cnf

# 获取所有的段
function get_all_segments
{
        echo `sed -n '/^\[.*\]/p' $FILE_NAME | sed -e 's/\[//g' -e 's/\]//g'`
}

# 统计每一段中配置项的个数
function count_items_in_segment
{
        # grep -v "^$" 删除空行
        # grep -v "^#" 删除注释行
        items=`sed -n "/^\[$1\]/,/^\[.*\]/p" $FILE_NAME | grep -v "^#" | grep -v "^$" | grep -v "^\[.*\]"`

        index=0
        for item in $items
        do
                index=`expr $index + 1`
        done

        echo $index
}


line=0
for seg in `get_all_segments`
do

        line=$(($line+1))
        sum=`count_items_in_segment $seg`
        echo "$line $seg: $sum"

done

my.cnf如下所示:

[client]
port=3306
socket=/tmp/mysql.socket

#ThisSegmentForserver
[server]
innodb_buffer_pool_size=91750M
innodb_buffer_pool_instances=8
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb_data_file_path=ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=2G
innodb_log_files_in_group=2
innodb_max_undo_log_size=4G
innodb_undo_directory=undolog
innodb_undo_tablespaces=95

#thisisonlyforthemysqldstandalonedaemon
[mysqld]
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
sort_buffer_size=16M
join_buffer_size=16M
thread_cache_size=3000
interactive_timeout=600
wait_timeout=600

#ThisSegmentFormysqld_safe
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
max_connections=1000
open_files_limit=65535
thread_stack=512K
external-locking=FALSE
max_allowed_packet=32M

#thisisonlyforembeddedserver
[embedded]
gtid_mode=on
enforce_gtid_consistency=1
log_slave_updates
slave-rows-search-algorithms='INDEX_SCAN,HASH_SCAN'
binlog_format=row
binlog_checksum=1
relay_log_recovery=1
relay-log-purge=1


#usethisgroupforoptionsthatolderserversdon'tunderstand
[mysqld-5.5]
key_buffer_size=32M
read_buffer_size=8M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
myisam_sort_buffer_size=128M
myisam_max_sort_file_size=10G
myisam_repair_threads=1
lock_wait_timeout=3600
explicit_defaults_for_timestamp=1
innodb_file_per_table=1

结果如下所示:

[flw@nlp2 67]$ sh mysql_process.sh
1 client: 2
2 server: 12
3 mysqld: 12
4 mysqld_safe: 7
5 embedded: 8
6 mysqld-5.5: 10

6. 利用sed删除文件内容

删除/etc/passwd中以yarn开头的行到最后的所有行

sed -i '/^yarn/,$d' passwd

删除配置文件中的所有注释行(#前面可能有空格)

sed -i '/\d*#/d' nginx.conf

7, 利用sed修改文件内容

在这里插入图片描述

7. 利用sed追加文件内容

在这里插入图片描述

a

在第10行到第20行,每行后(后面一行)追加 “leihou”

sed -i '10,20a leihou' passwd

i

匹配到以yarn开头的行,在匹配行前面(前面一行)追加 “alielie”

sed -i '/^yarn/i alielie' passwd

r

将/etc/fstab文件的内容追加到passwd文件的第20行后面

sed -i '20r /etc/fstab' passwd

w

将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中

sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd

Ⅲ awk

1. awk工作模式介绍

awk是一个文本处理工具,通常用于处理数据并生成结果报告。

语法格式

  • 第一种:awk 'BEGIN{}[pattern]{commands}END{}' file_name
  • 第二种:standard output | awk 'BEGIN{}[pattern]{commands}END{}'

[] 代表可以不写

语法格式说明

语法格式解释
BEGIN{}正式处理数据之前执行
pattern匹配模式,可以不写
{commands}处理命令,可能多行
END{}处理完所有匹配数据后执行

2. awk的内置变量

在这里插入图片描述

在这里插入图片描述

例子:

$0, $1
[flw@nlp2 72]$ awk '{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[flw@nlp2 72]$


[flw@nlp2 72]$ awk 'BEGIN{FS=":"}{print $1}' passwd     # FS=":" 分隔符是:
root
bin
[flw@nlp2 72]$

NF
[flw@nlp2 72]$ cat list
Hadoop  Spark Flume
Java     Python JavaScript       Go
Hermione Harry Voldemort
[flw@nlp2 72]$
[flw@nlp2 72]$ awk '{print $1}' list            # 默认是以空格或者TAB为分隔符
Hadoop
Java
Hermione
[flw@nlp2 72]$
[flw@nlp2 72]$ awk '{print NF}' list            # 输出每一行字段个数
3
4
3
[flw@nlp2 72]$
NR, FNR
[flw@nlp2 72]$ awk '{print NR}' list passwd     # 行号
1
2
3
4
5
[flw@nlp2 72]$
[flw@nlp2 72]$ awk '{print FNR}' list passwd    # 行号,每个文件单独记数
1
2
3
1
2
FS, RS

默认以 空格TAB 为分隔符

[flw@nlp2 72]$ cat list2
Hadoop|Sparkr:Flume--Java|Pythonr:JavaScript:Go--Hermione|Harry:Voldemort
[flw@nlp2 72]$
[flw@nlp2 72]$ awk 'BEGIN{FS=":";RS="--"}{print $2}' list2
Flume
JavaScript
Voldemort

[flw@nlp2 72]$ awk 'BEGIN{FS=":";RS="--"}{print $1}' list2
Hadoop|Sparkr
Java|Pythonr
Hermione|Harry
[flw@nlp2 72]$
OFS, ORS

在这里插入图片描述

FILENAME
[flw@nlp2 72]$ cat list
Hadoop Sparkr Flume
Java Pythonr JavaScript Go
Hermione Harry Voldemort
[flw@nlp2 72]$
[flw@nlp2 72]$
[flw@nlp2 72]$ awk '{print FILENAME}' list
list
list
list

3. awk格式化输出printf

printf的格式说明符

在这里插入图片描述

最常用的是前两种。

printf的修饰符

在这里插入图片描述

例子

# %-20s: "-"左对齐; 20表示字符串的长度是20
[flw@nlp2 72]$ awk 'BEGIN{FS=":"}{printf "%-20s %-20s-\n", $1, $2}' passwd
root                 x                   -
bin                  x                   -
[flw@nlp2 72]$

4. awk模式匹配的两种用法

  • 第一种模式匹配:RegExp(正则表达式)
  • 第二种模式匹配:关系运算匹配

例子

1. 正则表达式

匹配 /etc/passwd 文件行中含义root字符串的所有行

awk '/root/{print $0}' passwd

匹配 /etc/passwd 文件行中以yarn开头的所有行

awk '/^yarn/{print $0}' passwd
2. 关系运算

在这里插入图片描述

以:为分隔符,匹配 /etc/passwd 文件中第3个字段小于50的所有行信息

awk 'BEGIN{FS=":"}$3<50{print $0}' passwd

以:为分隔符,匹配 /etc/passwd 文件中第3个字段等于/bin/bash的所有行信息

awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd

以:为分隔符,匹配 /etc/passwd 文件中第3个字段为包含3个以上数字的所有行信息

awk 'BEGIN{S=":"}$3~/[0-9]{3,}/{print $0}' passwd

以:为分隔符,匹配 /etc/passwd 文件中第1个字段为root或者bin的所有行信息

awk 'BEGIN{FS=":"}$1=="root"||$1=="bin"{print $0}' passwd

以:为分隔符,匹配 /etc/passwd 文件中第3个字段小于50且第4个字段大于59的所有行信息

awk 'BEGIN{FS=":"} $3<50 && $4>50 {print $0}' passwd

5. awk中表达式的用法

在这里插入图片描述

[flw@nlp2 72]$ awk 'BEGIN{var=20;var1="hello";print var, var1}'
20 hello
[flw@nlp2 72]$

计算passwd中的空白行数量

awk '/^$/{sum++}END{print sum}' passwd

计算学生课程分数平均值

[flw@nlp2 76]$ cat txt
蓉儿    80      90      96      98
盈盈    93      98      92      91
赵敏    85      95      75      90
赫敏    78      88      98      100
[flw@nlp2 76]$
[flw@nlp2 76]$
[flw@nlp2 76]$ awk 'BEGIN{printf "%-16s%-16s%-16s%-16s%-16s%-16s\n", "name", "chinese", "english", "math", "physics", "average"}{sum=$2+$3+$4+$5;ave=sum/4;printf "%-16s%-16s%-16s%-16s%-16s%-16s\n", $1, $2, $3, $4, $5, ave}' txt
name            chinese         english         math            physics         average
蓉儿              80              90              96              98              91
盈盈              93              98              92              91              93.5
赵敏              85              95              75              90              86.25
赫敏              78              88              98              100             91
[flw@nlp2 76]$

6. awk动作中的条件及循环语句

6.1 条件语句

在这里插入图片描述

例子
1

以:为分隔符,只打印/etc/passwd中第3个字符案的数值在50-100范围内的行信息

awk 'BEGIN{FS=":"}$3>=50 && $3<=100{print $0}' passwd

# 或者

awk 'BEGIN{FS=":"}{if($3>=50 && $3<=100) print $0}' passwd
2

以:为分隔符,以:为分隔符,只打印/etc/passwd中第3个字符案的数值小于50或者大于100的行信息

awk 'BEGIN{FS=":"}{if($3<50){ printf "%-10s%-5d\n", "小于50:", $3} else if($3>100) {printf "%-10s%-5d\n", "大于100:", $3}}' passwd

或者可以把配置项写在文件中,如下:

在这里插入图片描述

6.2 循环语句

6.2.1 while循环

在这里插入图片描述

6.2.2 do-while循环

在这里插入图片描述

6.2.3 for循环

在这里插入图片描述

6.2.4 例子
1

计算1+2+…+100的和

[flw@nlp2 78]$ cat while.awk
BEGIN{
        while(i<=100) {
                sum += i
                i++
        }
        print sum
}
[flw@nlp2 78]$
[flw@nlp2 78]$
[flw@nlp2 78]$ awk -f script1.awk passwd
5050
[flw@nlp2 78]$

计算每门课的平均成绩

[flw@nlp2 78]$ cat student.awk
BEGIN{
        score_chinese=0
        score_english=0
        score_math=0
        score_physics=0
        count=0

        printf "%-16s%-16s%-16s%-16s%-16s\n", "name", "chinese", "english", "math", "physics"
}
{
        score_chinese+=$2
        score_english+=$3
        score_math+=$4
        score_physics+=$5
        count++

         printf "%-16s%-16s%-16s%-16s%-16s\n", $1, $2, $3, $4, $5

}
END{
        score_chinese/=count
        score_english/=count
        score_math/=count
        score_physics/=count
        printf "%-16s%-16s%-16s%-16s%-16s\n", "平均", score_chinese, score_english, score_math, score_physics
}
[flw@nlp2 78]$
[flw@nlp2 78]$
[flw@nlp2 78]$ awk -f student.awk txt
name            chinese         english         math            physics
蓉儿              80              90              96              98
盈盈              93              98              92              91
赵敏              85              95              75              90
赫敏              78              88              98              100
平均              84              92.75           90.25           94.75
[flw@nlp2 78]$

7. awk中的字符串函数

在这里插入图片描述

例子

以:为分隔符,返回/etc/passwd中每行中每个字段的长度

[flw@nlp2 79]$ cat e1.awk
BEGIN{
        FS=":"
}
{
        for(i=1;i<=NF;i++) {
                if (i!=NF) {
                        printf "%d:", length($i)
                }else {
                        printf "%d", length($i)
                }
        }
        print ""            # print 自带换行
}
[flw@nlp2 79]$
[flw@nlp2 79]$ awk -f e1.awk passwd
4:1:1:1:4:5:9
3:1:1:1:3:4:13
# ..
[flw@nlp2 79]$

搜索字符串 “I have a dream” 中出现 “ea” 字符串的位置

[flw@nlp2 79]$ awk 'BEGIN{printf "%d\n", index("I have a dream", "ea")}'    # 起始位置是1
12

# 或者

[flw@nlp2 79]$ awk 'BEGIN{printf "%d\n", match("I have a dream", "ea")}'

将字符串 “Hadoop is a bigdata Framework” 全部 转换为大写

[flw@nlp2 79]$ awk 'BEGIN{printf "%s\n", tolower("Hadoop is a bigdata Framework")}'
hadoop is a bigdata framework

将字符串 “蓉儿 盈盈 赵敏 赫敏” 按空格分隔,分隔后每部分保存到数组array中

[flw@nlp2 79]$ awk 'BEGIN{split("蓉儿 盈盈 赵敏 赫敏", arr, " "); print arr[0]}'

[flw@nlp2 79]$ awk 'BEGIN{split("蓉儿 盈盈 赵敏 赫敏", arr, " "); print arr[1]}'
蓉儿
[flw@nlp2 79]$

awk 中数组和字符串的下标都是从1开始记数

搜索字符串 “Tranction 2345 start:Select * from master” 中第一个数字出现的位置

[flw@nlp2 79]$ awk 'BEGIN{printf "%d\n", match("Tranction 2345 start:Select * from master", /[0-9]/)}'
11
[flw@nlp2 79]$ 

在sed和awk中,如果要使用正则表达式,必须使用 /RegEpr/ 这种形式

截取字符串 “transaction start” 的子串,截取条件从第4个字符开始,截取5位

[flw@nlp2 79]$ awk 'BEGIN{printf "%s\n", substr("transaction start", 4, 5)}'
nsact

替换字符串 “Transaction 243 Start, Event ID:9002” 中第一个匹配到的数字串为 $ 符号

[flw@nlp2 79]$ awk 'BEGIN{a="Transaction 243 Start, Event ID:9002";sub(/[0-9]+/, "$", a);printf "%s\n", a}'
Transaction $ Start, Event ID:9002



[flw@nlp2 79]$ awk 'BEGIN{a="Transaction 243 Start, Event ID:9002";gsub(/[0-9]+/, "$", a);printf "%s\n", a}'
Transaction $ Start, Event ID:$

8. awk中的常用选项

在这里插入图片描述

1. -v

[flw@nlp2 79]$ num1=20
[flw@nlp2 79]$ var="leihou"
[flw@nlp2 79]$
[flw@nlp2 79]$
[flw@nlp2 79]$ awk -v num2="$num1" -v var1="$var" 'BEGIN{printf "%d--%s\n", num2, var1}'
20--leihou
[flw@nlp2 79]$

2. -F

[flw@nlp2 79]$ awk 'BEGIN={FS=":"}{print $1}' passwd

# 等价于

[flw@nlp2 79]$ awk -F ":" '{print $1}' passwd

9. awk中数组的用法

在这里插入图片描述
在这里插入图片描述

例子

  1. 统计主机上所有的TCp连接,并统计不同状态的连接数
netstat -ntlp | grep tcp | awk '{array[$6]++}END{for (a in array) {printf "%-10s%-10s\n",a, array[a]}}'
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值