美文网首页
shell三剑客

shell三剑客

作者: test小星星 | 来源:发表于2019-06-15 00:17 被阅读0次

shell的三剑客


  • grep用来文本搜索,支持正则表达式
  • awk用来数据切片
  • sed用来修改文件数据

grep


grep 是一行一行循环匹配,匹配到相应的值时会先输出,然后换行继续匹配再换行直到所有的内容都匹配完。

常用参数

  • -n 显示行号
  • -i 忽略大小写
  • -o 精准匹配'
  • E 使用扩展正则表达式
  • -v 反转查找,即输出与查找条件不相符合的行
  • -A :后面可加数字,为 after 的意思,除了列出该行外,后续的 n 行也列出来
  • -B :后面可加数字,为 befer 的意思,除了列出该行外,前面的 n 行也列出来
  • --color=auto 可将正确的那个撷取数据列出颜色
  • grep -n -A3 -B2 --color=auto '20428'

实例1
先创建了一个test文件输入以下内容
echo "hello from testerhome,this is for grep test" > test
通过grep匹配test文件中的hello from testerhome

[tmp]$ grep "hello from testerhome" test
输出:hello from testerhome,this is for grep test
# 加上-o精准匹配
grep  -o "hello from testerhome" test
输出:test:hello from testerhome
# 不加-o会把包含匹配信息所在行中的所有内容输出(不在一行的不会输出)所以内
# 加-o只会输出匹配的信息,不会输出其他多余的信息

实例2,管道匹配

# 匹配 c
[tmp]$ echo abcd | grep -o c # 将管道前面的输出内容 作为后面的输入内容
输出:c

实例3,匹配网页内容

# 通过百度搜索关键字,然后通过正则匹配出搜索结果约xxx的内容,关键字以文件的形式作为参数循环传入
1. 创建文件 vim  baidu.keywrod
2. 输入关键字 
python 
ios 
shell
3. 输出命令
while read k; do echo $k; curl -s http://www.baidu.com/s?wd=$k; done < baidu.keyword 
| grep "结果约[0-9,]*"

执行结果


执行结果

分析结果

  • while read k; do echo $k; 循环读取内容,这里通过重定向输入到baidu.keywrod这个文件,去读取文件中的内容
  • curl -s http://www.baidu.com/s?wd=$k 这个是请求百度搜索地址,将夺取的内容作为参数传给wd 。 -s 会忽略掉一些curl请求的相关信息
  • | grep "结果约[0-9,]*" 通过管道命令 后面的gerp+正则匹配得到想要的结果

实例4,查看/etc/xxx.conf文件中除了以"#"开头的行(一般为注释)和空行以外的所有内容

[tmp]$ grep -v "^#" /etc/xxx.conf | grep -v "^#"

awk


awk 可以处理后续接的文件,也可以读取来自前个指令的标准输出,比较倾向于一行当中分成数个“字段”来处理。

一般格式
awk '条件类型1{动作1} 条件类型2{动作2} ...' filename

  • awk 'BEGIN{}END{}' 开始和结束
  • awk '/Running/' 正则匹配
  • awk '/aa/,/bb/' 区间选择
  • awk '$2~/xxx/' 字段匹配
  • awk 'NR==2' 取第二行
  • awk 'NR>1' 去掉第一行

脚本格式

awk 
'BEGIN{
  初始化语句 
}
{
  pattern{actions};
  pattern{actions};
  ...
}
END{
  读取所有输入行后执行语句
}'
  • 如果BEGIN区块存在,awk首先执行它里面包含的动作指令。
  • 当awk读完所有的输入行后,如果存在END区域,执行END区域的指令。
  • pattern(条件)可以是以下两种类型:
    1. 正则表达式:/正则表达式/
    2. 布尔表达式:表达式成立,触发相应的actions执行,如 5>3{print}
  • actions(动作)是由许多awk指令构成
    1. awk的I/O指令有print、printf()、getline等
    2. awk的流程控制指令有if...else...、 while() {...}等
    3. 所有 awk 的动作,亦即在 {} 内的动作,如果有需要多个指令辅助时,可利用分号“;”间隔, 或者直接以[Enter] 按键来隔开每个指令
    4. 与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。
  • awk 后面接两个单引号并加上大括号 {} 来设置想要对数据进行的处理动作。
  • awk 主要是处理“每一行的字段内的数据”,而默认的“字段的分隔符号为 "空白键" 或 "[tab]键" ”!
    也就是说,比如有这样一行内容“hello shell”, awk就会当成是两列$1取第一列的数据,$2取第二列的数据。

实例

  1. 打印1~10的自然数
[tem]$ awk 'BEGIN{while(++x<=10) print x}'
1
2
3
4
5
6
7
8
9
10
  1. 取出帐号与登陆者的 IP ,且帐号与 IP 之间以 [tab] 隔开
# 查看登陆者ip
[tmp]$ last -n 5
177**250 pts/26       182.**.120.43    Mon Jun 24 16:47   still logged in   
000**481 pts/20       114.**2.105.123  Mon Jun 24 16:38   still logged in   
504**406 pts/29       122.**2.15.42    Mon Jun 24 16:24   still logged in   
171**144 pts/16       101.**4.84.70    Mon Jun 24 15:55   still logged in   
101**869 pts/8        123.**0.4.245    Mon Jun 24 15:55   still logged in  

# 取出帐号与登陆者的 IP ,且帐号与 IP 之间以 [tab] 隔开
[tmp]$ last -n 5 | awk '{print $1 "\t" $3}'
000**481        114.**2.105.123
504**406        122.**2.15.42
171**144        101.**4.84.70
101**869        123.**0.4.245
298**968        202.**5.145.242
  • 在 awk 的括号内,每一行的每个字段都是有变量名称的,那就是 $1, $2... 等变量名称。以上面的例子来说,000**481 是 $1 ,因为他是第一栏嘛!至于114.**2.105.123 是第三栏, 所以他就是$3 啦!后面此类推,$NF代表最后一个字段。还有个变量!那就是 $0 ,$0 代表“一整列数据”的意思。

  • 整个 awk 的处理流程是:

    1. 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中;
    2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";
    3. 做完所有的动作与条件类型;
    4. 若还有后续的“行”的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止

awk内置变量

变量名称 代表意义
NF 每一行 ($0) 拥有的字段总数
NR 目前 awk 所处理的是“第几行”数据
FS 目前字段的分隔字符,默认是空白键
RS 行分隔符,默认是换行
FNR 统计awk读取过的总行数
OFS 输出数据的字段分隔符
ORS 输出数据的行分隔符
FILENAME 当前输入文件名

我们继续以上面 last -n 5 的例子来做说明,如果我想要:

  • 列出每一行的帐号(就是 $1);
  • 列出目前处理的行数(就是 awk 内的 NR 变量)
  • 并且说明,该行有多少字段(就是 awk 内的 NF 变量)
[tmp]$ last -n 5| awk '{print $1 "\t 当前行数: " NR "\t 当前行总段数 " NF}'     
02**2304         当前行数: 1     当前行总段数 10
72**2968         当前行数: 2     当前行总段数 10
95**6181         当前行数: 3     当前行总段数 10
17**8250         当前行数: 4     当前行总段数 10
00**6481         当前行数: 5     当前行总段数 10

实例2

  1. 在 /etc/passwd 当中是以冒号 ":" 来作为字段的分隔, 该文件中第一字段为帐号,第三字段则是 UID。那假设我要查阅,第三栏小于 10 以下的数据,并且仅列出帐号与第三栏。
[tmp]$ cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
root:x:0:0:root:/root:/bin/bash  
bin      1
daemon   2
adm      3
lp       4
sync     5
shutdown         6
halt     7
mail     8
  1. 找出nginx日志文件中某个时间段的日志
cat  access.log | awk '$4 >="[28/June/2019:00:00:00" && $4 <="[28/June/2019:23:59:59"{print $0}'  > 2019/06/28-access.log

sed


sed 本身也是一个管道命令,可以分析 standard input ,而且 sed 还可以将数据进行取代、删除、新增、截取特定行等等的功能

格式
sed [-nefr] [动作]
选项与参数:
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到屏幕上。但如果加上 -n 参数后,则只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令行界面上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以执行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正则表达式的语法。(默认是基础正则表达式语法)
-i :直接修改读取的文件内容,而不是由屏幕输出。

动作说明: [n1[,n2]]function
n1, n2 :不见得会存在,一般代表“选择进行动作的行数”,举例来说,如果我的动作是需要在 10 到 20 行之间进行的,则“ 10,20[动作行为] ”

function 有下面这些咚咚:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
i:插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以取代匹配到的值!通常这个 s 的动作可以搭配正则表达式!
例如 1,20s/old/new/g就是啦!

实例1

# 将 /etc/passwd 的内容列出并且打印行号,同时,请将第 2~5 行删除!
[tem]$ nl /etc/passwd | sed '2,5d'
  1 root:x:0:0:root:/root:/bin/bash
  6 sync:x:5:0:sync:/sbin:/bin/sync
  7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
# 那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行了

# 在第二行后(亦即是加在第三行)加上“hello shell”字样!
[tem]$ nl /etc/passwd | sed '2a hello shell'
  1 root:x:0:0:root:/root:/bin/bash
  2 bin:x:1:1:bin:/bin:/sbin/nologin
  hello shell
  3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

# 如果要新增多行每一行之间都必须要以反斜线“ \ ”来进行新行的增加
[tem]$ nl /etc/passwd | sed '2a hello shell \
> hello world'
  1 root:x:0:0:root:/root:/bin/bash
  2 bin:x:1:1:bin:/bin:/sbin/nologin
  hello shell
  hello world
  3 daemon:x:2:2:daemon:/sbin:/sbin/nologin

# 取出 11~20 行
[tem]$ nl /etc/passwd  | sed -n '11,20p'  
   11  games:x:12:100:games:/usr/games:/sbin/nologin
   12  ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
   13  nobody:x:99:99:Nobody:/:/sbin/nologin
   14  systemd-bus-proxy:x:999:998:systemd Bus Proxy:/:/sbin/nologin
   15  systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
   16  dbus:x:81:81:System message bus:/:/sbin/nologin
   17  polkitd:x:998:997:User for polkitd:/:/sbin/nologin
   18  tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
   19  sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
   20  postfix:x:89:89::/var/spool/postfix:/sbin/nologin

请注意:

  1. sed 后面接的动作,请务必以 '' 两个单引号括住喔!
  2. 如果有多个动作 使用 -e 分隔 如,nl /etc/passwd | sed -n -e '1,10p' -e '2,5d' -e '6i hello'

部分数据的搜索并取代
sed 's/要被取代的字串/新的字串/g'

实例2
取出ip地址


#先观察原始讯息,利用 /sbin/ifconfig eth0 查询 IP 
[tem]$ /sbin/ifconfig eth0 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.19.147.8  netmask 255.255.240.0  broadcast 172.19.159.255
        ether 00:16:3e:04:1c:75  txqueuelen 1000  (Ethernet)
        RX packets 101946929  bytes 30358246998 (28.2 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 84401729  bytes 45138874295 (42.0 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

#  取出172.19.147.8
[tem]$ /sbin/ifconfig eth0 | grep "inet" | sed 's/.*inet//g' | sed 's/ *netmask.*//g'
 172.19.147.8
说明:
1. 先用grep过滤出包含inet的行
2. 然后使用sed干掉ip地址前面的空字符串以及inet
3. 最后把 ip地址后面字符串也干掉

补充正则


字符匹配:
.任意单个字符
[]指定范围的字符
[^]不在指定范围的字符

次数匹配:
* 匹配前面字符0次或者任意次
? 0或1次
+ 1次或多次
{m} 匹配m次
{m,n} 至少m,至多n次

位置:
^ 行首
$ 行尾
^$ 空行
分组:
() 表示一个整体
egrep ‘r(oo)|(at)o‘ 1.txt 匹配roo或者ato
或者:
|
a|b a或b
C|cat C或cat
(C|c)at Cat或cat

补充一个好用的命令xargs


  • xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。
  • xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
  • xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。

实例
定义一个测试文件,内有多行文本数据:

$ cat test.txt

a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z

多行输入单行输出:

$ cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z

-n 选项单行转多行

$ echo "a b c d e f g h i j k l m n o p q r s t u v w x y z" | xargs -n2
a b
c d
e f
g h
i j
k l
m n
o p
q r
s t
u v
w x
y z

# -n  num 后面加次数,表示命令在执行的时候一次要使用几个参数的意思,默认是用所有的。

-d 选项可以自定义一个分隔符

$ echo "abcXabcXabcX" | xargs -dX
abc abc abc 

# 结合-n使用
echo "abcXabcXabcX" | xargs -dX -n1
abc
abc
abc


补充Perl正则

$ echo "Hello, my name is aming."|grep -oP '(?<=Hello, ).*(?= aming.)'
my name is

说明
这意思是,-P 可以让grep使用perl的正则表达式语法,因为perl的正则更加多元化,能实现更加复杂的场景。

相关文章

  • Shell编程、part5

    本节内容 1. 三剑客简介 2. sed命令详解 3. awk命令详解 文本处理三剑客 在 Shell 下使用这些...

  • 六.Shell之字符串高级用法(expr)

    Shell中对字符串处理命令主要有两种,一种为前面Shell三剑客之一的awk,另一种为即将介绍的expr。 1....

  • shell三剑客

    shell的三剑客 grep用来文本搜索,支持正则表达式 awk用来数据切片 sed用来修改文件数据 grep g...

  • shell三剑客

    awk、grep、sed是linux操作文本的三大利器,合称文本三剑客,也是必须掌握的linux命令之一。 正则表...

  • sed的认识和基本应用

    1.Sed 介绍 sed全名叫stream deitor,流编辑器。作为shell文本处理三剑客之一的sed,其不...

  • 2018-09-09

    用linux自带的shell的三剑客进行文本过滤操作:目的:从一个已经存在的文件中每次读取一个变量(一行),然后删...

  • shell三剑客之sed

    学习的内容来自于Linux Shell脚本攻略(2) 内容只做了简单的记录,方便自己学习 shell 命令查询地址...

  • shell三剑客之awk

    学习的内容来自于Linux Shell脚本攻略(2) 内容只做了简单的记录,方便自己学习 shell 命令查询地址...

  • shell三剑客之grep

    学习的内容来自于Linux Shell脚本攻略(2) 内容只做了简单的记录,方便自己学习 shell 命令查询地址...

  • shell三剑客之grep!

    背景 对于很多的测试人员来说,grep命令都很熟悉,用的最多的比如去查找指定的进程:ps -ef | grep *...

网友评论

      本文标题:shell三剑客

      本文链接:https://www.haomeiwen.com/subject/buimfctx.html