grep
grep的基本用法
grep命令是支持正则表达式的一个多用途文本搜索工具,一般格式为
grep 选项 模式 文件
选项 | 意义 |
---|---|
-c | 只输出匹配行的数量 |
-i | 搜索时忽略大小写 |
-h | 查询多文件时不显示文件名 |
-l | 只列出符合匹配的文件名,而不列出具体的匹配行 |
-n | 列出所有的匹配行,并显示行号 |
-s | 不显示不存在或无匹配文本的错误信息 |
-v | 显示不包含匹配文本的所有行 |
-w | 匹配整词 |
-x | 匹配正行 |
-r | 递归搜索,不仅搜索当前目录,而且搜索子目录 |
-q | 禁止输出任何结果,以退出状态表示搜索是否成功 |
-b | 打印匹配行距文件头部的偏移量,以字节为单位 |
-o | 与-b选项结合使用,打印匹配的词距文件头部的偏移量,以字节为单位 |
-E | 支持扩展的正则表达式 |
-F | 不支持正则表达式,按照字符串的字面意思进行匹配 |
grep命令的模式十分灵活,可以是字符串,也可以是变量,还可以是正则表达式。注意,无论模式是何种形式,只要模式中包含空格,就需要使用双引号将模式引起来。
grep与正则表达式
- 匹配行首,用元字符
^
设置大小写,用
-i
匹配重复字符,用
.
,*
转义符,用
\
-
POSIX字符类
类名 意义 [:upper:] 表示大写字母[A~Z] [:lower:] 表示小写字母[a~z] [:digit:] 表示阿拉伯数字[0~9] [:alnum:] 表示大小写字母和阿拉伯数字 [:space:] 表示空格键和TAB键 [:alpha:] 表示大小写字母 [:cntrl:] 表示Ctrl [:graph:]或[:print:] 表示ASCII码 [:xdigit:] 表示16进制数字[09AFa~f] 精确匹配:用
\<\>
或字符,grep需要加上-E选项才能支持它,用
|
表示
grep命令族
grep: 标准grep命令
egrep: 扩展grep命令,支持基本和拓展正则表达式
fgrep: 快速grep命令,不支持正则表达式
sed命令
sed是一个非交互式文本编辑器,它可对文本文件和标准输入进行编辑,标准输入可以是来自键盘输入、文件重定向、字符串、变量,甚至来自管道的文本。sed适用于以下三中场合:
- 编辑相对交互式文本编辑器而言太大的文件。
- 编辑命令太复杂,在交互式文本编辑器中难以输入的情况。
- 对文件扫描一遍,但是需要执行多个编辑函数的情况。
基本用法
sed
只是对缓冲区中原始文件的副本进行编辑,并不编辑原始文件。如果需要保存文件改动的内容,需要将输出重定向到另一个文件。
调用sed
有三种方式,一种为Shell命令行方式,另外两种是将sed
命令写入脚本文件,然后执行该脚本文件。
- 在Shell命令行输入命令调用
sed
,格式为sed [选项] 'sed命令' 输入文件
。 - 将
sed
命令插入脚本文件后,然后通过sed
命令调用它,格式为sed [选项] -f sed 脚本文件 输入文件
。 - 将
sed
命令插入脚本文件后,最常用的方法是设置该脚本文件为可以执行,然后直接执行该脚本文件,格式为./sed脚本文件 输入文件
第三种方式脚本文件需要以sha-bang(#!)
符号开头。无论哪种方式,如果没有指定输入文件,sed
将从标准输入接收输入。常用选项有三个
选项 | 意义 |
---|---|
-n | 不打印所有的行到标准输出 |
-e | 表示将下一个字符串解析为sed编辑命令,如果只传递一个,可以省略 |
-f | 表示正在调用sed脚本文件 |
sed
命令主要由定位文本行和sed
编辑命令两部分组成,有两种方式定位文本:
- 使用行号,指定一行,或者指定行号范围
- 用正则表达式
选项 | 意义 |
---|---|
x | x为指定行号 |
x,y | 指定从x到y的行号范围 |
/pattern/ | 查询包含模式的行 |
/pattern/pattern/ | 查询包含两个模式的行 |
/pattern/,x | 从pattern匹配行到x号行 |
x,/pattern/ | 上一条反过来 |
x,y! | 查询不包括x和y行号的行 |
编辑命令
选项 | 意义 |
---|---|
p | 打印匹配行 |
= | 打印文件行号 |
a\ | 在定位行号后追加文本信息 |
i\ | 在定位行号之前插入文本信息 |
d | 删除定位行 |
c\ | 用新文本替代定位文本 |
s | 使用替换模式替换相应模式 |
r | 从另一个文件中读文本 |
w | 将文本写入到一个文件 |
y | 变换字符 |
q | 第一个模式匹配后退出 |
l | 显示与八进制ASCII码等价的控制字符 |
{} | 在定位行执行的命令组 |
n | 读取下一个输入行,用下一个命令处理新的行 |
h | 将模式缓冲区的文本复制到保持缓冲区 |
H | ...追加到保持缓冲区 |
x | 互换模式缓冲区和保持缓冲区内容 |
g | 将保持模式缓冲区的内容复制到模式缓冲区 |
G | ....追加到模式缓冲区 |
示例
测试文件内容:
This is a Certificate Request file:
It should be mailed to zawu@seu.edu.cn
=====================================================
Certificate Subject:
/O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
To install this user certificate, please save this e-mail message into the following file.
/home/alloy/linuxshell/CH02/usercert.pem
sed -n
: 不打印sed编辑对象的全部内容
wsx@wsx-ubuntu:~/桌面$ sed -n '1p' input
This is a Certificate Request file:
wsx@wsx-ubuntu:~/桌面$ sed '1p' input
This is a Certificate Request file:
This is a Certificate Request file:
It should be mailed to zawu@seu.edu.cn
=====================================================
Certificate Subject:
/O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
To install this user certificate, please save this e-mail message into the following file.
/home/alloy/linuxshell/CH02/usercert.pem
利用sed命令打印范围行:
wsx@wsx-ubuntu:~/桌面$ sed -n '3,6p' input
It should be mailed to zawu@seu.edu.cn
=====================================================
Certificate Subject:
sed -e
: sed传递多个编辑命令时使用
wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/=' input
1
6
wsx@wsx-ubuntu:~/桌面$ sed -n -e '/Certificate/p' input -e '/Certificate/=' input
This is a Certificate Request file:
1
Certificate Subject:
6
sed -f
:调用sed脚本文件时才起作用
wsx@wsx-ubuntu:~/桌面$ sed '/file:/a\We append a new line.' input
This is a Certificate Request file:
We append a new line.
It should be mailed to zawu@seu.edu.cn
=====================================================
Certificate Subject:
/O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus
The above string is known as your user certificate subject, and t uniquely identifies theis user. $88
To install this user certificate, please save this e-mail message into the following file.
/home/alloy/linuxshell/CH02/usercert.pem
脚本用法:
#! /bin/sed -f
/file:/a\ #a\表示在此处添加文本
# 添加文本
We append a new line.\
We append a another line.
sed基本编辑命令可以放在单引号内,也可放在单引号外。
sed文本定位的一组例子
-
匹配元字符,用转义符
\
进行屏蔽wsx@wsx-ubuntu:~/桌面$ sed -n '/\./p' input It should be mailed to zawu@seu.edu.cn /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certificate subject, and t uniquely identifies theis user. $88 To install this user certificate, please save this e-mail message into the following file. /home/alloy/linuxshell/CH02/usercert.pem
-
使用元字符进行匹配
$
在sed命令中表示最后一行wsx@wsx-ubuntu:~/桌面$ sed -n '$p' input /home/alloy/linuxshell/CH02/usercert.pem
-
!
符号,打印不在2-10的行wsx@wsx-ubuntu:~/桌面$ sed -n '2,10!p' input This is a Certificate Request file: To install this user certificate, please save this e-mail message into the following file. /home/alloy/linuxshell/CH02/usercert.pem
-
使用行号和关键字匹配限定行范围
wsx@wsx-ubuntu:~/桌面$ sed -n '/seugrid/,$p' input /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certificate subject, and t uniquely identifies theis user. $88 To install this user certificate, please save this e-mail message into the following file. /home/alloy/linuxshell/CH02/usercert.pem
sed基本编辑命令的一组例子
-
插入文本:运行脚本,以输入文件名作为参数
#!/bin/sed -f /file:/i\ # i\表示此处换行插入文本 We insert a new line.
-
修改文本
#!/bin/sed -f /file:/c\ #c\表示此处换行修改文本 We modify this line #修改文本内容
-
删除文本,符号是
d
,不带\
,与其他命令有所区别,非常灵活。下面删除第一行和最后一行。wsx@wsx-ubuntu:~/桌面$ sed '1d' input It should be mailed to zawu@seu.edu.cn ===================================================== Certificate Subject: /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certificate subject, and t uniquely identifies theis user. $88 To install this user certificate, please save this e-mail message into the following file. /home/alloy/linuxshell/CH02/usercert.pem wsx@wsx-ubuntu:~/桌面$ sed '$d' input This is a Certificate Request file: It should be mailed to zawu@seu.edu.cn ===================================================== Certificate Subject: /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certificate subject, and t uniquely identifies theis user. $88 To install this user certificate, please save this e-mail message into the following file.
-
替换文本,格式
s/被替换的字符串/新字符串/[替换选项]
选项 意义 g 全局匹配替换(替换所有的) p 与-n选项结合,只打印替换行 w 文件名 表示将输出定向到一个文件 sx@wsx-ubuntu:~/桌面$ sed 's/Certificate/CERTIFICATE/' input This is a CERTIFICATE Request file: It should be mailed to zawu@seu.edu.cn ===================================================== CERTIFICATE Subject: /O=Grid/OU=GlobusTest/OU=simpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certificate subject, and t uniquely identifies theis user. $88 To install this user certificate, please save this e-mail message into the following file. /home/alloy/linuxshell/CH02/usercert.pem wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/p' input This is a CERTIFICATE Request file: CERTIFICATE Subject:
-
写入到一个新文件
wsx@wsx-ubuntu:~/桌面$ sed -n 's/Certificate/CERTIFICATE/pg' input This is a CERTIFICATE Request file: CERTIFICATE Subject: wsx@wsx-ubuntu:~/桌面$ wsx@wsx-ubuntu:~/桌面$ sed -n '1,5 w output' input wsx@wsx-ubuntu:~/桌面$ cat output This is a Certificate Request file: It should be mailed to zawu@seu.edu.cn =====================================================
从文件中可读入文本,格式
指定地址 r 文件名
。退出命令:
q
-
变换命令:sed命令的
y
表示字符变换(不等长时会报错)wsx@wsx-ubuntu:~/桌面$ sed 'y/fmj/FMJ/' input This is a CertiFicate Request File: It should be Mailed to zawu@seu.edu.cn ===================================================== CertiFicate SubJect: /O=Grid/OU=GlobusTest/OU=siMpleCA-seugridl.seu.edu.cn/OU=seu.edu.cn/CN=globus The above string is known as your user certiFicate subJect, and t uniquely identiFies theis user. $88 To install this user certiFicate, please save this e-Mail Message into the Following File. /hoMe/alloy/linuxshell/CH02/usercert.peM
显示控制字符:控制字符就是非打印字符,如退格键、F1键等。使用
sed l
命令。-
在命令行执行命令组,用
{}
符号,与-e
选项功能类似。wsx@wsx-ubuntu:~/桌面$ sed -n '/Certificate/{p;=}' input This is a Certificate Request file: 1 Certificate Subject: 6
awk编程
awk是三位前辈开发的编程语言,awk是三位创建者的首字母。基本语言与C类似。
目前,使用的是gawk,Linux系统中/bin目录下有awk
和gawk
两个命令,前者实际上是后者的链接。利用gawk
语言可以实现数据查找、抽取文件中的数据、创建管道流命令等功能。
我们可以简单地将awk
编程模型分位三个阶段:
- 读输入文件执行的执行代码段(由BEGIN关键字标识)
- 读取输入文件时执行代码段
- 读输入文件之后的执行代码段(由END关键字标识)
调用方法分为两种:Sehll命令行方式;脚本执行。
awk模式匹配
任何awk语句都由模式和动作组成。模式是一组用于测试输入行是否需要执行动作的规则,动作是包含语句、函数和表达式的执行过程。awk
支持所有的正则表达式元字符,以及?
和+
两个扩展元字符。
wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print "This is a blank line."}' input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
单引号中间为awk命令,由两部分组成,以“/”符号分隔,^$
是模式,花括号部分是动作。该awk表示一旦读入的输入文件是空行,就打印后面的字符串This is a blank line
。
使用脚本(将命令输入一个文件中):
wsx@wsx-ubuntu:~/桌面$ awk -f src.awk input
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
This is a blank line.
内容不止这些,我们先谈谈其他概念。
记录和域
awk认为输入文件是结构化的,awk将每个输入文件行定义为记录,行中的每一个字符串定义为域,域之间用空格、TAB键或其他符号进行分隔,分隔域的符号就叫分隔符。(这个结构化概念需要理解,很多命令和编程中都有涉及)
wsx@wsx-ubuntu:~/桌面$ awk '{print $2,$1,$4,$3}' sturecord
Hao Li 025------------ njue
Ju Zhang 025---------- nju
Bin Wang 025------ seu
wsx@wsx-ubuntu:~/桌面$ awk '{print $0}' sturecord
Li Hao njue 025------------
Zhang Ju nju 025----------
Wang Bin seu 025------
可以通过对域的操作对文本进行重新排列,也可以用print $0
输入所有域。
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {one=1;two=2}{print $(one+two)}' sturecord
njue
nju
seu
BEGIN
字段中定义one
和two
两个变量并赋值。
-F
选项用来改变分隔符,例如只以'\t'为分隔符。
wsx@wsx-ubuntu:~/桌面$ awk -F'\t' '{print $2}' sturecord
025------------
025----------
025------
注意-F
与-f
的区别。
awk还提供了另一种更方便的方法改变分隔符。
wsx@wsx-ubuntu:~/桌面$ cat sturecord
Li Hao,njue,025------------
Zhang Ju,nju,025----------
Wang Bin,seu,025------
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=","}{print $1, $3}' sturecord
Li Hao 025------------
Zhang Ju 025----------
Wang Bin 025------
关系和布尔运算符
awk定义了一组关系运算符用于awk模式匹配。如下表
运算符 | 意义 |
---|---|
< | 小于 |
> | 大于 |
<= | 小于或等于 |
>= | 大于或等于 |
== | 等于 |
!= | 不等于 |
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
用/etc/passwd文件做个例子
# 第1域匹配root
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd
# 全部域匹配root
root:x:0:0:root:/root:/bin/bash
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
# 全部域不匹配nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin
awk条件语句与C类似,有if语句,if/else语句以及if/else else语句三种。
下面是支持的布尔运算符
运算符 | 意义 |
---|---|
|| | 逻辑或 |
&& | 逻辑与 |
! | 逻辑非 |
# 多条件精确匹配
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd
# 多条件模糊匹配
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
wsx@wsx-ubuntu:~/桌面$ awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:110::/var/run/dbus:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
lightdm:x:108:114:Light Display Manager:/var/lib/lightdm:/bin/false
whoopsie:x:109:116::/nonexistent:/bin/false
avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
wsx:x:1000:1000:wsx,,,:/home/wsx:/bin/bash
nx:x:123:1001::/var/NX/nx:/etc/NX/nxserver
表达式
一个awk表达式可以由数值、字符常量、变量、操作符、函数和正则表达式自由组合而成。
运算符 | 意义 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 模 |
^或** | 乘方 |
++x | 在返回x之前,x变量加1 |
x++ | 在返回x之后,x变量加1 |
wsx@wsx-ubuntu:~/桌面$ awk '/^$/{print x+=1}' input
1
2
3
4
5
系统变量
awk定义了很多内建变量用于设置环境信息,我们称为系统变量。分为两种:一种用于改变awk的默认值,例如域分隔符;第二种用于定义系统值,在处理文本时可以读取这些系统值。
变量名 | 意义 |
---|---|
$n | 当前记录的第n个域,域用FS分隔 |
$0 | 记录的所有域 |
ARGC | 命令行参数的数量 |
ARGIND | 命令行中当前文件的位置(从0开始标号) |
ARGV | 命令行参数的数组 |
CONVFMT | 数字转换格式 |
ENVIRON | 环境变量关联数组 |
ERRNO | 最后一个系统错误的描述 |
FIELDWIDTHS | 字段宽度列表,以空格键分隔 |
FILENAME | 当前文件名 |
FNR | 浏览文件的记录数 |
FS | 字段分隔符,默认是空格键 |
IGNORECASE | 布尔变量,如果为真,则进行忽略大小写的匹配 |
NF | 当前记录中的域数量 |
NR | 当前记录数 |
OFMT | 数字的输出格式 |
OFS | 输出域分隔符,默认是空格键 |
ORS | 输出记录分隔符,默认是换行符 |
RLENGTH | 由match函数所匹配的字符串长度 |
RS | 记录分隔符,默认是空格键 |
RSTART | 由match函数所匹配的字符串的第1个位置 |
SUBSEP | 数组下标分隔符,默认值是\034 |
格式化输出
awk借鉴C语言的语法,定义了printf
输出语句。基本语法如下:
printf(格式控制符, 参数)
格式控制符分为修饰符和格式符两种,如下:
修饰符 | 意义 |
---|---|
- | 左对齐 |
width | 域的步长 |
.prec | 小数点右边的位数 |
运算符 | 意义 |
---|---|
%c | ASCII字符 |
%d | 整型数 |
%e | 浮点数,科学计数法 |
%f | 浮点数 |
%o | 八进制数 |
%s | 字符串 |
%x | 十六进制数 |
内置字符串函数
awk提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分隔等功能,下表列出:
函数名 | 意义 |
---|---|
gsub(r,s) | 在输入文件中用s替换r |
gsub(r,s,t) | 在t中用s替换r |
index(s,t) | 返回s中字符串第一个t的位置 |
length(s) | 返回s的长度 |
match(s,t) | 测试s是否包含匹配t的字符串 |
split(r,s,t) | 在t上将r分为序列s |
sub(r,s,t) | 将t中第1次出现的r替换为s |
substr(r,s) | 返回字符串r中从s开始的后缀部分 |
substr(r,s,t) | 返回字符串r中从s开始长度为t的后缀部分 |
向awk脚本传递参数
awk脚本内的变量可以在命令行中进行赋值,实现向awk脚本传递参数,变量赋值放在脚本之后、输入文件之前,格式为:
awk脚本 parameter=value 输入文件
条件语句和循环语句
看起来基本和C一样,框架如下——
if (条件表达式)
动作1
[else
动作2]
while(条件表达式)
动作
do
动作
while(条件表达式)
for(设置计数器初值; 测试计数器; 计数器变化)
动作
数组
数组是存储一系列值的变量,可通过索引来访问数组的值,索引需要用中括号括起,数组的基本格式为:
array[index]=value
形式和C一样,但awk数组无需定义数组类型和大小,可以直接赋值后使用。一般用在for循环中
for (variable in array)
do somethng with array[variable]
更多操作可以查看:http://man.linuxde.net/awk