Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【3.23】awk参考 #83

Open
vieyahn2017 opened this issue Mar 23, 2023 · 5 comments
Open

【3.23】awk参考 #83

vieyahn2017 opened this issue Mar 23, 2023 · 5 comments

Comments

@vieyahn2017
Copy link
Owner

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

@vieyahn2017
Copy link
Owner Author

vieyahn2017 commented Mar 23, 2023

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

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

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

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

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

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

FILENAME∶ 被处理的文件名

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

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

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

@vieyahn2017
Copy link
Owner Author

awk与getline

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

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

@vieyahn2017
Copy link
Owner Author

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
Copy link
Owner Author

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant