vieyahn2017 / shellv

shell command test and study
4 stars 1 forks source link

【3.23】awk参考 #83

Open vieyahn2017 opened 1 year ago

vieyahn2017 commented 1 year ago

https://www.cnblogs.com/JC123/p/15073361.html

vieyahn2017 commented 1 year ago

shell脚本—awk 一、awk

1、工作原理

2、命令格式

3、awk常见的内建变量

二、awk具体操作

1、按行输出文本

2、按字段输出文本

3、通过管道、双引号调用shell命令

三。awk与getline

四、awk的其他用法

1、指定分隔符来分隔字符串

2、使用awk创建数组并循环

vieyahn2017 commented 1 year ago

awk常见的内建变量(可直接使用)

FS:列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-F"作用相同

NF∶ 当前处理的行的字段个数

NR∶ 当前处理的行的行号(序数)

$0∶当前处理的行的整行内容

$n∶ 当前处理行的第n个字段(第n列)

FILENAME∶ 被处理的文件名

RS∶ 行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是’\n’

FNR:awk当前读取的记录数,其变量值小于等于NR(比如当读取第二个文件时,FNR是从0开始重新计数,而NR不会)

NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件

vieyahn2017 commented 1 year ago

awk与getline

(1)、当getline左右无重定向符“<”或“|”时,getline作用于当前文件,读入当前文件的第一行给其后跟的变量var或$0;应该注意到,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的

(2)、当getline左右有重定向符“<”或“|”时,getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行

vieyahn2017 commented 1 year ago

awk实现替换字符串中指定位置之间的内容

显示第xx行的第yy列的一个字符

sed -n 'xx,xxp' file | awk '{print substr($0,yy,1);}'

修改第xx行的第yy列的一个字符Chr,并保存为新文件

awk -F "" 'BEGIN { OFS="" }{if(NR == xx) for(i=yy;i<=yy;i++) {$i="Chr";} print }' file > newfile

file内容: 123abc456aababc789abcqweabcrtyabc

替换第9个字符到第19个字符之间的abc为xyz:

awk -F "" 'BEGIN { OFS="" } {for(i=9;i<=19;i++) if(i=="a" && (i+1)=="b" && $(i+2)=="c"){i="x"; (i+1)="y";$(i+2)="z"}print }' file

首先通过设定FS,将每个字符看成一个域然后通过for循环进行遍历,经过判断找出abc这样连续的三个字符后进行重新赋值,最后输出,记住,如果用sub、gsub替换,请分析好替换的内容.

REF:

http://blog.chinaunix.net/uid-25696473-id-3246669.html

vieyahn2017 commented 1 year ago

Linux中awk的gsub函数用法 一。遇到的问题:

问题:echo "a b c 2011-11-22 a:d" | awk '$4=gsub(/-/,"",$4)'为啥 输出后 2011-11-22 变成 2 了?

解答: gsub(/-/,"",$4)的值是2【在赋值的情况下是这样的~】,你将2赋值给$4 ,gsub返回的是替换的次数。 如下是测试结果: [root@Test230 ~]# echo "a b c 2011-11-22 a:d" | awk '$4=gsub(/-/,"",$4)' a b c 2 a:d

看另一种情况,只是替换的话~

[root@sor-sys config]# echo "a b c 2011-11-22 a:d" | awk 'gsub(/-/,"",$4)' a b c 20111122 a:d [root@sor-sys config]# echo "a b c 2011-11-22 a:d" | awk 'gsub(/-/,"_",$4)' a b c 2011_11_22 a:d

二。实例详解

下面我们来总结一下这个gsub的用法:

有一个文本文件data.test的内容如下:

0001|20081223efskjfdj|EREADFASDLKJCV 0002|20081208djfksdaa|JDKFJALSDJFsddf 0003|20081208efskjfdj|EREADFASDLKJCV 0004|20081211djfksdaa1234|JDKFJALSDJFsddf

以'|'为分隔, 现要将第二个域字母前的数字去掉,其他地方都不变, 输出为: 0001|efskjfdj|EREADFASDLKJCV 0002|djfksdaa|JDKFJALSDJFsddf 0003|efskjfdj|EREADFASDLKJCV 0004|djfksdaa1234|JDKFJALSDJFsddf

解法:

awk -F '|' '{sub(/[0-9]+/,"",$2);print $0}' data.test

三。sub和gsub的区别

sub匹配第一次出现的符合模式的字符串,相当于 sed 's//'
gsub匹配所有的符合模式的字符串,相当于 sed 's//g'

awk的sub函数用法: sub函数匹配指定域/记录中最大、最靠左边的子字符串的正则表达式,并用替换字符串替换这些字符串。如果没有指定目标字符串就默认使用整个记录,替换只发生在第一次匹配的时候。

实例: $ awk '{ sub(/test/, "mytest"); print }' testfile $ awk '{ sub(/test/, "mytest", $1); print }' testfile 第一个例子在整个记录中匹配,替换只发生在第一次匹配发生的时候。 第二个例子在整个记录的第一个域中进行匹配,替换只发生在第一次匹配发生的时候

gsub函数作用如sub,但它在整个文档中进行匹配。

实例: $ awk '{ gsub(/test/, "mytest"); print }' testfile $ awk '{ gsub(/test/, "mytest", $1); print }' testfile 第一个例子在整个文档中匹配test,匹配的都被替换成mytest。 第二个例子在整个文档的第一个域中匹配,所有匹配的都被替换成mytest。

只有当记录中的域有改变的时候 ,指定0FS变量才有用, 如果记录中的域无变化, 指定OFS产生不了实际效果。

awk -F'|' -v OFS='|' '{ gsub(/[0-9]/, "", $3); print $0; }' data.txt

将把第三个域中所有数字都去掉。