linux 重定向到 数组中,shell脚本抽取文本文件中指定字符串的方法:sed+grep方法、awk+grep方法(必要时能够联合sed以及grep)、grep+cut方法...

在linux中常常要对一些动态的文本文件抽取指定的字符串,好比执行ps命令后想要获取指定的运行进程(如ps本身)的PID号(同一个进程每次启动的时候pid号是随机分配的)。该怎么办呢?固然,能够用一些截取字符串的方法,这里介绍一下用2种方法来解决这类问题。linux

1、sed+grep方法:正则表达式

首先大概了解一下sed,sed是linux里面一个非交互性的文本流编辑器(好长的定义,反正我听起来我很拗口)。解释2点:shell

1,非交互性:这里非交互性是指sed工具并不直接编辑目的文本文件,而是编辑目的文件的一个缓存拷贝,只可以修改拷贝文件,不会对源文件有任何的改动!也就是说编辑并不在目的文件现场!好比我想要编辑example.log文件,若是用vi编辑器必须直接打开example.log文件,而后在里面编辑。而sed是编辑example.log文件的一个拷贝,那么你可能要问了,这个拷贝在哪儿呢?这个拷贝在缓存里面,不须要咱们本身拷贝,只要你调用了sed工具来编辑,系统自动会帮咱们拷贝出一个example.log文件供你去编辑,从而保护好源文件不被随意改动。数组

2,文本流:文本流是指咱们经过必定的shell指令对文本进行编辑,而不想vi编辑器同样须要把文件打开以后才可以进行编辑。好比我要删除example.log里面的第一行。vi里面必须先打开文件,而后选中第一行,再按下backspace键删除。若是你使用sed命令的话,就只要执行如下一行代码就能够干脆利落的删除掉第一行:sed '1d' example.log。如今能够知道,sed工具无需打开文件再进行操做,而是经过一系列命令操做文本流,因此叫作文本流编辑器。缓存

好,如今来解决问题:bash

举个例子,好比使用ipsec的时候常常须要使用的一个命令是setkey -D来查看spi是否正常生成了。而每次ipsec链接的时候产生的spi是不同的,当spi产生失误的时候,就会出现spi=000000000;如今我想经过必定的shell脚本获取spi的值。setkey -D产生而定输出以下图app

9b55afe464b1491d92a9c917.html

咱们在说sed,固然使用sed来解决该问题。编辑器

明确一下咱们的目的:咱们的目的是要获取上图中的一段数据:spi=152056446,而且每次若是ipsec从新启动的时候spi后面的数据会不同(但长度同样,而且都是数字)。那么咱们想到天然要用到正则表达式来匹配该段数据,而后输出到一个变量或者文件供咱们后续使用。工具

再来看看sed给咱们提供了什么方法:sed能够很方便的把某一行打印出来,sed -n '2p' example.log会打印出第二行。也就是说sed很容易获取行,这显然不能知足咱们的需求。sed不会这么简单!sed还提供了删除,追加,插入,替换等丰富的方法来对一段文本进行编辑。学习

删除某一行:

9b55afe464b1491d92a9c917.html

追加:把hello,i was appended here 追加到有national这一行的的后面。

9b55afe464b1491d92a9c917.html

替换:sed 's/source string/destination string/' example.log

那么,我想既然sed能够很是方便的获取到某一行数据,而它又可以对文本进行编辑,那么,个人想法是,先用sed对文本进行必定的编辑,把目标字符串编辑到某一行内,我就很是方便的获取到了

好,照着这条思路走:

1,编辑文本,把目标字符串放到单独的一行里面来:观察以后能够看出,该段目的字符串spi=152056446(0x0910327e)先后都有空格,那么就用空格做为从新编辑的标记位,先后换行。

输入命令:sed 's/ /\n/g' example.log。解释下命令,s是替换的标记,第一个/ /里面有一个空格,意思是查找全部含有空格的行,最后的g代表要对该行的全部空格进行查询,而不仅是查询到第一个就查询下一行,第二个/\n/是一个换行符,结合前面的空格查询语法,能够对全部的空格替换成换行符。里面的命令执行后会把文本从新编排,遇到空格就换行,这样,目标字符串就已经到了单独的一行里面去了!!!

2,获取目标行字符串:如今就很简单了,咱们能够用grep来获取(grep "spi" example.log),也能够用sed来获取(sed '/spi/p' example),把屏幕输出重定向到一个文件里面去,或者赋给一个变量,这样,咱们抽取目标字符串的任务就完成了!!!

是否是很简单!!!

9b55afe464b1491d92a9c917.html好,下面来看awk方法

2、awk方法:

一样的,首先来大概了解一下awk方法的精髓,awk方法主要是对文本进行“列”的操做,这个对比一下sed和grep可能咱们更容易理解一些,sed和grep主要是对文本进行“行”的操做,awk会把每一列都取一个名字,从第一列开始:分别为$1,$2...$n,好吧,这样就能够按照名字来分别操做列了。

好吧,如今咱们来实例操做一下。

咱们从ps输出里面去查询指定进程名字的PID,在个人终端直接输入ps x以后会显示当前进程的名字,其部分截图以下:

9b55afe464b1491d92a9c917.html

如今我想获取的是当前ps x输出里面的进程名为上图中红圈部分nautilus的PID值1355,因为相同进程会在不一样的时候开启的时候所获取到的PID号不同,因此当前的PID值1355实际上是个不必定的数字。因而,咱们只能经过进程名字nautilus来获取当前PID。好,目的明确以后进行操做:

1,配合使用管道,使用grep获取到包含nautilus的行:

9b55afe464b1491d92a9c917.html

发现有2个nautilus,好吧,那咱们就来操做2个nautilus的PID,只是须要配合使用一下sed,没事,就当复习一下;

2,如今是awk派上用场的时候了:

9b55afe464b1491d92a9c917.html

继续使用管道,能够看到,利用命令

9b55afe464b1491d92a9c917.html能够获得进程名为nautilus的PID列:1355和1858。

这里先来个小插曲,简单介绍一下awk命令的语法,awk基本语法为:awk [-F] "field-operator" 'comand' inputfiles,-F和field-operator一块儿使用,field-operator是域分隔符,若是不使用-F选项,则默认的域分隔符为空格。后面command命令通常须要用一堆“{}”括起来,而后进行必要的操做,比较全面一点的command命令'{if($1~/^A/) print $1}',翻译一下这个命令就是,若是第一列($1)里面有匹配(~)正则表达式(/^A/)的话,那么就输出(print)到标准输出。须要注意的是,条件必需要用一堆"()"括起来,正则表达式须要用“//”括起来。固然,彻底能够不要条件匹配,能够直接输出指定列,如'{print $1}'。好,awk就介绍到这里,不过awk是一个很是很是强大的文本格式化抽取的工具,须要专门的学习。后面我再写一个关于awk学习的总结。

3,如今须要利用sed对"行"的操做了,咱们获取到的第一行就是第一个nautilus的PID值,上面咱们已经介绍了sed命令,因此很简单的,接着上面的管道,输入如下命令:

9b55afe464b1491d92a9c917.html

很快,咱们就能够获得第一个nautilus的PID值了

9b55afe464b1491d92a9c917.html

是否是很简单,就简单的三部操做,grep——awk——sed,这三真是文本操做里面的拼命三郎啊

3、如今来稍微介绍一下cut方法

cut也是一个比较强大的工具,能够对一行字符串进行多种模式匹配的剪切操做,也能够对一个排列很是整齐的文本进行操做,下面经过2个例子来大体说明 一下cut的操做。

1,先说明cut对一行字符串的操做:

在终端执行echo $PATH命令,能够得到当前默认的bash路径,以下图:

9b55afe464b1491d92a9c917.html

其中每个路径都被一个“:”分隔开来,如今我想获取第1个和第2个冒号之间的路径,使用cut将会很是之方便,在终端输入命令:

9b55afe464b1491d92a9c917.html

确实,咱们获取到了第一个冒号与第二个冒号之间的字符串“/usr/local/bin”,如今来稍微解析一下这条命令,-d和':'一块儿把管道输入的一行字符串进行了域的分隔,每个分隔符(在这里是个冒号“:”)前面的字符串被称为一个域,如有n个分隔符,这个域的编号则从1开始到n+1,第1个分隔符前面的字符串为第一个域。这个域对应在该命令行则是-f后面的数字2,因此该命令`cut -d ':' -f 2`表达的意思是输出第二个分隔符“:”以前的域。

若是咱们执行

9b55afe464b1491d92a9c917.html

或者是cut -d ':' -f 2-4,则能够输出第2个和第四个域的字符串,可是还多了一个分隔符,这点我也没搞懂。

上面是是用分隔符对一行字符串进行操做,下面咱们队字符串的每个字母当成一个数组里面的元素,只是第一个元素是从1开始,而不是传统数组的0开始。这样能够进行另一种cut操做,如今先定义一个字符串变量,并从中截取出1-5之间的字符:

9b55afe464b1491d92a9c917.html

可见,这条命令很好的把字符串“hello world”从第2个字母到第5个字母cut了下来,把最后的参数进行一下修改,以下:

9b55afe464b1491d92a9c917.html

则能够截取到第2个字符以及后面的全部的字符。

2,cut对格式化整齐的文本进行操做:

9b55afe464b1491d92a9c917.html

这是一段格式化比较整齐的数据,每一行前面的“declare -x”都是如出一辙的,我如今想把这一段给去掉:

9b55afe464b1491d92a9c917.html

其实咱们发现对该文本的操做跟上的一行字符串的操做没什么区别。

那么就验证一下对分隔符的操做是否也同样:

9b55afe464b1491d92a9c917.html

发现结果确实是同样。这说明cut会把一个文本里面的每一行都独立的对待,而后再操做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值