linux 文本操作命令 awk 和 sed 的简单实用

       awk是对文本,按行进行处理。它可以将文本,按行以某一字符进行分割,分成不同的段,其中$0代表整个文本行,$n代表第n段,而默认的分隔符是”空格键”或”Tab键”。

Awk运作的模式如下:

简易例子如下:

如果要取出账号与登陆者的ip,且账号与ip之间用tab键隔开,则命令如下:

注意:

1、”\t”必须得用双引号引住,否则是识别不了的。

2、发现第2行和第4行有点乱,那是因为在原始的last中,第一段和第三段就是那样的,所以,用awk时,一定要确认好数据的格式。

3、发现上面命令中,并没有”条件类型”的限制,那是因为我们要处理文本的每一行。

awk的处理流程:

从上述流程知,awk是以行为一次处理的单位,而以字段为最小的处理单位,那么awk如何知道所处理的数据有几行、几栏呢,这就需要awk的内建变量帮忙啦

简易例子:

显然,输出是账户名、awk当前处理的哪一行、awk当前处理行的字段数。

注意:awk所有的动作都是用单引号引住的,所以用print打印时,非变量的文字部分,一定要用双引号引住,包括用printf。

4.9.1 awk的逻辑运算符

既然命令中可以写”条件类型”,那自然需要一些逻辑运算啦,如下:

值得注意的是表格中没有=运算符,它和程序语言中一样,如果是直接给变量赋值,就是直接用的=,而不是’==’。

简易例子:

这个只是让你知道,passwd中的内容格式是什么,和下面的cat /etc/passwd 是不对应的。

显然,将文本行的分隔符改为了”:”,而且对于每一行,只有第三段的值<10,才输出第一个字段和第三个字段。但是奇怪的是,为什么第一行没有按指定的要求输出呢?

那是因为,在我们读入第一行时,那些变量$1,$2…… 还是以预设的空格为分隔,所以我们虽然定义了 FS=”:”,则仅能在第二行处理时才能生效,那么如何解决这个问题呢?

可以预先设定awk的变量,利用BEGIN这个关键词

注意:这个BEGIN 并不等价于”NR==1”,它表示在”NR==1”之前就进行处理了,相应的还有一个END呢。

4.9.2 awk实现计算功能

简易例子:

薪资数据表pay.txt如下:

Name    1st 2nd 3th
songbw  100 200 300
xiaosh  2   3   45
majf    7   8   9

用awk 命令实现薪资统计
 

(base) localhost:~ songbw$ cat pay.txt |\
> awk 'NR==1 {printf "%10s %10s %10s %10s %10s\n", $1, $2, $3, $4, "Total"}
> NR >= 2 {total = $2 + $3 + $4; printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total }'
      Name        1st        2nd        3th      Total
    songbw        100        200        300     600.00
    xiaosh          2          3         45      50.00
      majf          7          8          9      24.00

 

显然,上述是算每个人三个月工资的总和。

注意:

1、

2、格式化输出时,在printf的格式设定当中,务必加上’\n’,才能进行分行,而print 是不需要的!

3、与bash shell的变量不同,在awk当中,变量可以直接使用,不需要加$!

awk的动作{}也支持if(条件)哦,上述子,可以更改如下:

另外awk可以帮我们进行循环计算,这是属于高级课程,以后有需要再学吧。

简单小例子:

awk -F: '{if($1>10) {print $1}}'  /etc/passwd

以后稍微参考下,就可以写简单的if语句

 

参考地址:

http://phi.sinica.edu.tw/aspac/reports/94/94011/

http://linux.vbird.org/linux_basic/0330regularex/awk.pdf

 

4.9.3 awk打印引号

1、打印双引号

首先,awk 打印的字符串是要加引号的,如

awk '{print "songbw"}' generatorRecordings.sh

打印songbw这个字符串是要加引号的,那么正常逻辑打印双引号应该为 awk '{print """}' generatorRecordings.sh 

但是出现错误:

提示没有终止的字符串,提示很正确,因为三个双引号,两个双引号之间是一个string,但是现在只有三个,也就是说有一个字符串没有写完,解决办法,打印出来的引号需要用\转义,如下:

awk '{print "\""}' generatorRecordings.sh

 

2、打印单引号

awk '{print "'\''"}'       # 放大: awk '{print  "  '  \  '  '   " }'

使用一个双引号“”,然后在双引号里面加入两个单引号‘’,接着在两个单引号里面加入一个转义的单引号\',输出单引号。

例子

awk '{print "'\''"}'  generatorRecordings.sh

 

参考书籍:

鸟哥的linux私房菜

 

文本test.txt中内容:

# flume.conf: A single-node Flume configuration


# Name the components on this agent

a3.sources = r1  a3.channels = c1

a3.sinks = k1

a3.channels = c1

 

脚本try.sh中内容:
 

#!/bin/bash

i=4

sed 's/a3/a'$i'/'  test.txt

执行脚本try.sh后的结果:

发现,每一行的第一个匹配的都进行了改变

而打开test.txt后的内容和原来相比,并没有发生变化

如果想让test.txt文本中发生改变,需要加上-i 命令参数,如下,将

sed 's/a3/a'$i'/'  test.txt

改为

sed  -i 's/a3/a'$i'/'  test.txt

如果想让test.txt文本中所有匹配的都进行改变,需要加上/g,具体如下:

sed  -i 's/a3/a'$i'/g'  test.txt

sed具体用法如下

sed 's/原字符串/替换字符串/'


单引号里面,s表示替换,三根斜线中间是替换的样式,特殊字符需要使用反斜线”\”进行转义,但是单引号”‘”是没有办法用反斜线”\”转义的,这时候只要把命令中的单引号改为双引号就行了,例如:

代码如下:

sed "s/原字符串包含'/替换字符串包含'/" //要处理的字符包含单引号


命令中的三根斜线分隔符可以换成别的符号,这在要替换的内容有较多斜线是较为方便,只需要紧跟s定义即可,例如换成问号”?”:

代码如下:

sed 's?原字符串?替换字符串?' //自定义分隔符为问号


可以在末尾加g替换每一个匹配的关键字,否则只替换每行的第一个,例如:

代码如下:

sed 's/原字符串/替换字符串/g' //替换所有匹配关键字

配指定行的例子:

sed '2s/原字符串/替换字符串/g' //替换第2行
sed '$s/原字符串/替换字符串/g' //替换最后一行
sed '2,5s/原字符串/替换字符串/g' //替换2到5行
sed '2,$s/原字符串/替换字符串/g' //替换2到最后一行

 

发布了12 篇原创文章 · 获赞 2 · 访问量 1987

猜你喜欢

转载自blog.csdn.net/weileshenghuo1/article/details/104768706