grep、sed、awk、cut¶
1 grep¶
- 功能:打印匹配行
- 语法形式:
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
- 参数选项
- 基础操作
-i
:忽略大小写-w
:匹配整个单词,如匹配main,main111则不会匹配到-x
:匹配整行-m num
:最大匹配行数量,比如当一个文件原本有10个匹配行时,设置num=5,则只会打印5条匹配后-A num
:同时打印匹配行后num行-B num
:同时打印匹配行前num行-v
:反向匹配,输出非匹配行内容(正常是打印匹配行,指定了-v则打印非匹配行)-c
:统计匹配行数量,与-v一同使用则统计非匹配行数,如grep -cv main test.cc
-n
:输出匹配行的行号
- 多文件级操作
-l
:当查找多个文件时,打印匹配的文件名-L
:当查找多个文件时,打印非匹配的文件名
- 目录级操作
-r
或-R
:指定目录搜索而非文件,如grep --include=*.cc --exclude=test1.cc main -r test
,在test目录下,包含*.cc文件,排除test1.cc,匹配main--include=GLOB
:包含的文件,可以使用模式匹配--exclude=GLOB
:排除的文件,可以使用模式匹配--exclude-dir=DIR
:排除的子目录,通常在指定目录下有子目录,且不想要匹配时
2 pgrep¶
- 功能:基于给定条件来查找正在运行的程序的进程ID。(类似ps和grep的组合体)
- 语法:
pgrep [option] PATTERN
-u 用户名
:指定所属用户-G 用户组
:指定所属组-l
:列出进程名-d
:指定输出结果分割符,默认一行一个结果- 示例
$ ps -ef|grep here4|grep sshd
root 2868240 5518 0 15:01 ? 00:00:00 sshd: here4 [priv]
here4 2868262 2868240 0 15:01 ? 00:00:00 sshd: here4@pts/9
root 3315145 5518 0 17:36 ? 00:00:00 sshd: here4 [priv]
here4 3315159 3315145 0 17:36 ? 00:00:00 sshd: here4@pts/10
here4 3466706 3315177 0 18:25 pts/10 00:00:00 grep --color=auto sshd
$ pgrep -u here4 sshd
2868262
3315159
$ pgrep -l -u here4 sshd
2868262 sshd
3315159 sshd
$ pgrep -l -d ',' -u here4 sshd
2868262 sshd,3315159 sshd
3 awk¶
- 官方文档
- 简单教程
- 语法形式:管道可以取代files
awk [option] script files
awk [option] -f scriptfile files
- 功能:处理文本
-F 分隔符
:指定分割符(默认每行按空格分割),分隔符可以用单引号包裹,-F与分隔符间可以间隔开,也可以连在一起,如,-F ':'
或-F:
-f scriptfile
:指定脚本文件取代script-v 变量名=变量值
:赋值一个用户定义变量- 示例
# 对test.txt文本每行按空格或TAB分割,打印第1项和第3项的值
awk '{print $1,$3}' test.txt
# 对test.txt文本每行按;分割,打印第1项和第3项的值
awk -F; '{print $1,$3}' test.txt
# -F; 或者-F ';'
awk -F ';' '{print $1,$3}' test.txt
#用awk脚本分析test.txt,test.awk脚本作用与上面中的script一致
awk -f test.awk test.txt
- 概念
- 文件的一行称为 awk 的一个记录
- 使用特定分隔符分开的单词称为字段
3.1 awk 运算符¶
运算符 | 描述 |
---|---|
= += -= *= /= %= ^= **= |
赋值 |
?: | C条件表达式 |
| |
|
&& | 逻辑与 |
~ 和 !~ | 匹配正则表达式和不匹配正则表达式 |
< <= > >= != == |
关系运算符 |
空格 | 连接 |
+ - | 加,减 |
* / % | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ |
求幂 |
++ -- | 增加或减少,作为前缀或后缀 |
$ |
字段引用 |
in | 数组成员 |
3.2 awk内建变量¶
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由FS分隔 |
$0 | 完整的输入记录 |
ARGC | 命令行参数的数目 |
ARGIND | 命令行中当前文件的位置(从0开始算) |
ARGV | 包含命令行参数的数组 |
CONVFMT | 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组 |
ERRNO | 最后一个系统错误的描述 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔) |
FILENAME | 当前文件名 |
FNR | 各文件分别计数的行号 |
FS | 字段分隔符(默认是任何空格) |
IGNORECASE | 如果为真,则进行忽略大小写的匹配 |
NF | 一条记录的字段的数目 |
NR | 已经读出的记录数,就是行号,从1开始 |
OFMT | 数字的输出格式(默认值是%.6g) |
OFS | 输出字段分隔符,默认值与输入字段分隔符一致。 |
ORS | 输出记录分隔符(默认值是一个换行符) |
RLENGTH | 由match函数所匹配的字符串的长度 |
RS | 记录分隔符(默认是一个换行符) |
RSTART | 由match函数所匹配的字符串的第一个位置 |
SUBSEP | 数组下标分隔符(默认值是/034) |
3.3 awk 键值数组¶
awk支持数组,但key是字符串
3.4 awk 中print和printf的区别¶
- print在显示多个结果的时候以逗号分隔,结果将这几部分的内容自动使用分隔符进行分隔,且不需要添加换行符\n
- printf可以更加灵活的控制某一个字段的输出格式,通过使用诸如%-12s,%3.1f等格式化方法
$ echo -e "hello world bob\ngood bye tim"|awk '{print $1,$3}'
hello bob
good tim
$ echo -e "hello world bob\ngood bye tim"|awk '{printf"%s %s\n",$1,$3}'
hello bob
good tim
3.5 awk脚本语法¶
注意:当多条语句写在同一行上时,可以用分号来断开语句。 awk脚本分3部分: - BEGIN{ 这里面放的是执行前的语句 } - END{这里面放的是处理完所有的行后要执行的语句 } - {这里面放的是处理每一行时要执行的语句}
3.6 NR的使用¶
$ cat awk.file
Tom 男 19
Jim 男 20
alice 女 19
alma 女 18
$ awk 'NR==1,NR==3{print $0}' awk.file
Tom 男 19
Jim 男 20
alice 女 19
$ awk 'NR==2{print $0}' awk.file
Jim 男 20
3.7 awk if条件语句¶
注意:if语法与c语言中if完全相同 - 语法:当有多条语句时,可以用花括号包裹
if (condition_1)
action_1
else if (condition_2)
action_2
else
action_3
- 示例
$ awk 'BEGIN {num = 11; if (num % 2 == 0) printf "%d 是偶数\n", num;else printf "%d 是奇数\n", num}'
10 是偶数
3.8 awk for和while循环¶
注意:for和while语法与c语言中for和while完全相同 - 语法 - 示例
$ awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
1
2
3
4
5
$ awk 'BEGIN { i=0;while (++i<5) print i }'
1
2
3
4
$ awk 'BEGIN { i=0;do{print i} while(++i<5)}'
0
1
2
3
4
3.9 awk break和continue¶
注意:break和continue语法与c语言中break和continue完全相同 - 示例
$ awk 'BEGIN { i=0;do{if(i==3) break;else print i} while(++i<5)}'
0
1
2
4 sed¶
- 官方文档
- 参考文档
- 功能:流文本处理。sed每次处理一行文本,放入临时缓冲区中,处理完后,输出到标准输出流上(重定向改变输出目标)。
- 语法:
sed [选项]... {脚本(如果没有其他脚本)} [输入文件]
- 选项参数:
-e script
:用于串联多个匹配模式,将脚本指令添加到已有指令中-f scriptFile
:指定匹配模式的脚本文件-n
:不产生命令输出,使用print命令来完成输出,通常与p一起使用-i[suffix]
:直接修改文件,-i后面可以带上后缀,表示,修改原文件先备份,备份文件名在原文件名+后缀-r
:支持扩展正则表达式
- 脚本符号
s/pattern/replacement/flags
:替换字符,flags可选参数g
:全局匹配,默认只匹配第一次出现number
:匹配第number次匹配的
- 示例
# 待处理数据可以来自管道,也可以在命令行末尾指定文件路径
# s 用hi取代hello
$ echo "hello world"|sed "s/hello/hi/"
hi world
# 多个指令用;分割
$ echo "hello world"|sed -e "s/hello/hi/;s/world/boy/"
hi boy
4.1 -i修改文本¶
-i后可以加上备份文件名的后缀,这样会在原文件目录下生成备份文件
- 示例
$ cat file
hello world!
I'm happy!
$ sed -i.bak "s/hello/hi/" file
$ ls
file file.bak
$ cat file
hi world!
I'm happy!
4.2 -e添加多个匹配模式¶
$ sed -e "s/hello/hi/" -e "s/happy/fine/" file
hi world!
I'm fine!
4.3 -f指定脚本文件¶
# -f指定脚本文件
$ cat sed.script
s/hello/hi/
s/world/boy/
$ echo "hello world"|sed -f sed.script
hi boy
4.4 -n与p配合使用打印匹配行¶
# -n与p配合使用,只打印p指定的内容
$ cat sed.test
hello world
I'm a coder
$ sed -n 's/world/man/p' sed.test
hello man
$ sed 's/world/man/' sed.test
hello man
I'm a coder
4.5 选项统计¶
4.5.1 命令集¶
符号 | 功能 |
---|---|
a\ | 在当前行下面插入文本。 |
i\ | 前行上面插入文本。 |
c\ | 把选定的行改为新的文本。 |
d | 删除,删除选择的行。 |
D | 删除模板块的第一行。 |
s | 替换指定字符 |
h | 拷贝模板块的内容到内存中的缓冲区。 |
H | 追加模板块的内容到内存中的缓冲区。 |
g | 获得内存缓冲区的内容,并替代当前模板块中的文本。 |
G | 获得内存缓冲区的内容,并追加到当前模板块文本的后面。 |
l | 列表不能打印字符的清单。 |
n | 读取下一个输入行,用下一个命令处理新的行而不是用第一个命令。 |
N | 追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码。 |
p | 打印模板块的行。 |
P | (大写) 打印模板块的第一行。 |
q | 退出Sed。 |
b lable | 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。 |
r file | 从file中读行。 |
t label | if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 |
T label | 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾。 |
w file | 写并追加模板块到file末尾 |
W file | 写并追加模板块的第一行到file末尾 |
! | 表示后面的命令对所有没有被选定的行发生作用 |
= | 打印当前行号码。 |
# | 把注释扩展到下一个换行符以前。 |
4.5.2 替换集¶
符号 | 功能 |
---|---|
g | 表示行内全面替换。(默认每行只匹配第一个) |
ng | 表示每行只匹配前面n个。(比如2g,每行只匹配前面2个) |
i | 忽略大小写 |
p | 表示打印行。 |
w | 表示把行写入一个文件。 |
x | 表示互换模板块中的文本和缓冲区中的文本。 |
y | 表示把一个字符翻译为另外的字符(但是不用于正则表达式) |
\1 | 子串匹配标记 |
& | 已匹配字符串标记 |
4.5.3 匹配模式集¶
sed 能使用gnu正则表达式,尤其可以配合捕获组可以实现更强大的功能
符号 | 功能 | 示例 |
---|---|---|
^ | 匹配行开始 | /^hello/匹配所有以hello开头的行。 |
$ | 匹配行结束 | /world$/匹配所有以worlld结尾的行。 |
. | 匹配一个非换行符的任意字符 | /h..ld/匹配h后接2个任意字符,最后是ld的字符串。 |
* | 匹配0个或多个字符 | /*world/ 匹配所有模板是一个或多个空格后紧跟world的行。 |
[] | 匹配一个指定范围内的字符 | /[hH]ello/匹配hello或Hello。 |
[^] | 匹配一个不在指定范围内的字符 | /[^A-RT-Z]ed/ 匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行。 |
\(..\) |
匹配子串,保存匹配的字符(需要转义) | s/\(love\)able/\1rs/ ,loveable被替换成lovers。 |
& | 保存搜索字符用来替换其他字符 | s/love/I & you/,love这成I love you 。 |
\< | 匹配单词的开始 | /\<love/匹配包含以love开头的单词的行。 |
> | 匹配单词的结束 | /love>/匹配包含以love结尾的单词的行。 |
x{m} | 重复字符x,m次 | /0{5}/匹配包含5个0的行。 |
x{m,} | 重复字符x,至少m次 | /0{5,}/匹配至少有5个0的行。 |
x{m,n} | 重复字符x,至少m次,不多于n次 | /0{5,10}/匹配5~10个0的行 |
4.6 pattern匹配模式规则¶
/pattern/
:匹配pattern容行/pattern1/,/pattern2/
:匹配pattern1和pattern2行之间内容(包括匹配行)startline,/pattern/
:匹配startline行到pattern行之间内容。(如果pattern没有匹配,就会直接匹配到最后一行;如果startline超出了最大行,就匹配失败)/pattern/,endline
:匹配pattern行到endline行之间内容。(如果pattern行没有匹配到,匹配就失败;如果endline比pattern匹配所在行小,只会打印pattern匹配的行)linenum
:匹配第linenum行startline,endline
:匹配startline到endline之间的行startline,+N
:匹配startline及其后N行s/pattern/replacement/
:替换字符- 示例
shw@shu:~$ cat -n /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
4 sys:x:3:3:sys:/dev:/usr/sbin/nologin
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
11 uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
shw@shu:~$ sed -n "6,10p" /etc/passwd
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
shw@shu:~$ sed -n "6p" /etc/passwd
games:x:5:60:games:/usr/games:/usr/sbin/nologin
shw@shu:~$ sed -n "6,+2p" /etc/passwd
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
shw@shu:~$ sed -n "/games/,8p" /etc/passwd
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
shw@shu:~$ sed -n "8,/news/p" /etc/passwd
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
shw@shu:~$ sed -n "/^games/,/news/p" /etc/passwd
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
4.7 查询¶
4.7.1 p打印匹配行¶
- 模式语法:
/pattern/p
$ echo "hello world"|sed -n "/^hello/p"
hello world
4.8 修改¶
4.8.1 s替代匹配项¶
- 示例1:替换匹配项
$ echo "hello world"|sed 's/hello/hi/'
hi world
- 示例2:删除匹配项
# 利用空字符去替换
$ echo "hello world"|sed 's/hello//'
world
4.9 c改变匹配行¶
- 示例
$ echo -e "hello boy\nworld"|sed "/hello/c HELLO BOY"
HELLO BOY
world
4.10 增加¶
4.10.1 a匹配行后追加行¶
- 匹配模式语法:
/pattern/a匹配行后追加一行
$ echo hello world"|sed "/^hello/a I am studying sed"
I am studying sed
hello world
4.10.2 i匹配行前追加行¶
- 匹配模式语法:
/pattern/i匹配行前追加一行
$ echo hello world"|sed "/^hello/i I am studying sed"
I am studying sed
hello world
4.10.3 r将另一个文件内容追加到匹配行后面¶
- 匹配模式语法:
/pattern/r文件名
$ cat file
hello world
I am studying sed
$ echo "hello world"|sed "/^hello/r file"
hello world
hello world
I am studying sed
4.10.4 w将匹配内容保存到指定文件¶
- 匹配模式语法:
/pattern/w文件名
$ echo "hello world"|sed "/^hello/w file"
hello world
$ cat file
hello world
4.11 删除¶
4.11.1 删除匹配行¶
$ echo -e "hello\nworld"|sed '/he/d'
world
4.11.2 删除指定行¶
# 删除1-2行
$ echo -e "hello\nworld\nboy"|sed '1,2d'
boy
# 删除第1行
$ echo -e "hello\nworld\nboy"|sed '1d'
world
boy
# 删除第2行
$ echo -e "hello\nworld\nboy"|sed '2d'
hello
boy
# 删除从第一行到最后一行
$ echo -e "hello\nworld\nboy"|sed '1,$d'
# 删除最后一行
$ echo -e "hello\nworld\nboy"|sed '$d'
hello
world
4.11.3 删除空白行¶
$ echo -e "hello\n\nworld"
hello
world
$ echo -e "hello\n\nworld"|sed '/^$/d'
hello
world
4.12 {}命令组¶
- 功能:当命令是另一个匹配模式时,需要使用{}包裹命名
- 示例:
/男/p
是另一个匹配模式,需要用{}
包裹
$ sed -n '2,4{/男/p}' awk.file
Jim 男 20
$ sed -n '2,4/男/p' awk.file
sed:-e 表达式 #1,字符 4:未知的命令:“/”
$ echo -e "hello world\nboy"|sed -n '1,${/hello/{p;q}}'
hello world
4.13 多行命令¶
4.13.1 采用多行命令方式¶
- 在输入第1条命令后,按回车换行,输入第2条命令,以'结尾输入
$ seq 6|sed '1d
> 3d
> 5d'
2
4
6
4.13.2 使用;单行多条命令¶
在使用a、c、i (行号插入、改变行、行前插入)时,不能使用此方式,会被解析成单条命令。如下命令`Hello ; 2d`被当成了一条语句
```shell
$ seq 2 | sed '1aHello ; 2d'
1
Hello ; 2d
2
```
$ seq 6 |sed "1d;3s/./333/;5d"
2
333
4
6
4.13.3 使用-e指定多条命令方式¶
$ seq 6 |sed -e 1d -e 3d -e 5s/./555/
2
4
555
6
- 作用:针对匹配行再执行sed命令
# 2表示匹配第2行;{s/world/boy/;p}是对第2行的特殊处理,用boy替换匹配的world;p表示打印替换后的内容
$ echo -e "hello\nworld"|sed -n "2{s/world/boy/;p}"
boy
4.14 高阶使用技巧¶
4.14.1 在匹配行首添加字符¶
- 使用
&
表示匹配的任意内容
$ echo "hello world"|sed "s/hello/#&/"
#hello world
4.14.2 匹配的字符串&¶
$ echo -e "hello world"|sed 's/hello/[&]/'
[hello] world
4.14.3 匹配子串¶
子串是\(...\)
这里匹配的,由\1
,\2
等来表示第1额子串,第2个子串
$ echo -e "hello world"|sed 's/\(hello\) \(world\)/\2 \1/'
world hello
4.14.4 使用n每隔多少行跳过¶
# 1个n表示每隔1行,2个n表示每隔2行,执行后面的指令s/./x/ ,即用x替换任一个匹配的字符
$ seq 6 | sed 'n;n;s/./x/'
1
2
x
4
5
x
$ seq 6 | sed 'n;s/./x/'
1
x
3
x
5
x
5 cut¶
- 功能:以行为单位,提取指定数据
- 语法:
cut option file
-b [区域规则]
:选择指定字节-c [区域规则]
:选择指定字符;与-b不同在于,当字符是多字节时,比如汉字,一个汉字就是一个字符,而-b只会以8bit作为计数单位。-d [分割符]
:指定分隔符,默认以tab
分割-f [区域规则]
:与-d
结合使用,指定的分割区域区域规则
:M
:第M个字节、字符、区域,从1开始M,N,...
:第M和N个字节、字符、区域(多个用,分割)M-N
:第M到N个字节、字符、区域-N
行首到第N个字节、字符、区域M-
第M个字节、字符、区域到行尾
- 示例1:
-b
示例,-c
与之想同
# 选择第2个字节
$ echo "hello world"|cut -b 2
e
# 选择从第2字节开始,直到行尾的区域
$ echo "hello world"|cut -b 2-
ello world
# 选择从行首到第2字节的区域
$ echo "hello world"|cut -b -2
he
# 选择从第2字节到第6字节的区域
$ echo "hello world"|cut -b 2-6
ello
# 选择第2和第3个字节
$ echo "hello world"|cut -b 2,3
el
- 示例2:
-d
分隔符
$ echo "hello world boy,girl"|cut -d" " -f 2
world
$ echo "hello world boy,girl"|cut -d" " -f 3
boy,girl
$ echo "hello world boy,girl"|cut -d" " -f 2
world
$ echo "hello world boy,girl"|cut -d"," -f 2
girl
$ echo "hello world boy,girl"|cut -d"," -f 1
hello world boy
$ echo "hello world boy,girl"|cut -d" " -f -2
hello world
$ echo "hello world boy,girl"|cut -d" " -f 2-
world boy,girl
$ echo "hello world boy,girl"|cut -d" " -f 1,3
hello boy,girl