—re-interval
在标准的正则表达式中{m}表示匹配字符m次,即[A-Z]{m}表示匹配A到Z的任意一个字符m次。
,所以我们在awk中通常如下匹配:1
2
3
4
5cat test.txt
12 AT CG
7555 AAA AT
878 GGGG CTG
cat test.txt | awk 'BEGIN{FS=OFS="\t"} {for(i=1;i<=NF;i++) if ($i~/^[ATCG]{2}$/) print $i}'
空,什么也没有输出?
首先{m}属于基本的正则表达式,而awk只支持扩展的正则表达式;
awk要想使用{m,n}类型的正则表达式,必须向awk提供参数:—re-interval
。1
2
3
4cat test.txt | awk --re-interval 'BEGIN{FS=OFS="\t"} {for(i=1;i<=NF;i++) if ($i~/^[ATCG]{2}$/) print $i}'
AT
CG
AT
-v var=value or —asign var=value 赋值一个用户定义变量;
1 | $ awk -va=1 '{print $1,$1+a}' log.txt |
gensub()替换
1 | echo "123356" | awk '{print gensub("3","d",2)}' |
gensub(a,b,c,d) a:匹配的字符,b替换的字符,c为指定替换目标是第几次匹配(如1,2,g),d为指定替换目标是哪个域如$1,$2,若无d指$0,返回值为target替换后内容(未替换还是返回 target原内容)。
两个文本按条件合并
1 | [zpxu@node102 ~]$ cat 2.txt 1.txt |
命令解释:首先处理2.txt文件,a[$1]=$0相当与将$1为键,整个行$0为值的hash;当处理1.txt文件时,直接在键的数组a中匹配1.txt中的$1列,若匹配则输出1.txt的$1和其在对应2.txt中匹配到的值;
next与getline
awk code: ‘BEGIN{…}{Main Input}END{..}’
next 读入下一输入行并从(Main Input中的)第一个规则开始执行脚本。1
2
3
4
5
6
7
8
9[zpxu@node102 ~]$ cat data
name naughty
25 shandong
age 14
ah,here is test
[zpxu@node102 ~]$ awk '{if(NR==1){next} print $1,$2}' data
25 shandong
age 14
ah,here is
当记录行号等于1,就跳过当前行,其后面的print $1,$2也不会执行,读入下一行重新开始;
next合并多行为一行
可首先将两个或多个文件处理:cat a.txt b.txt | sort -n -k1 ,然后用next合并多行为一行来进行两个文本的按条件合并;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20cat data
web01[192.168.2.100]
httpd ok
tomcat ok
sendmail ok
web02[192.168.2.101]
httpd ok
postfix ok
web03[192.168.2.102]
mysqld ok
httpd ok
awk '/^web/{T=$0;next;} {print T":\t"$0;}' data
web01[192.168.2.100]: httpd ok
web01[192.168.2.100]: tomcat ok
web01[192.168.2.100]: sendmail ok
web02[192.168.2.101]: httpd ok
web02[192.168.2.101]: postfix ok
web03[192.168.2.102]: mysqld ok
web03[192.168.2.102]: httpd ok
#行首匹配到web时将这一整行赋值给T存储起来,并读入下一行,最后将T和下一行一起print;
与next相似,getline也是读取下一行数据。但是与next不同的是,next读取下一行之后,把控制权交给了awk脚本的顶部。但是getline却没有改变脚本的控制,读取下一行之后,继续运行当前的awk脚本。getline执行之后,会覆盖$0的内容。1
2
3
4
5
6
7[zpxu@node102 ~]$ cat d
$1=="name"{print $0;getline;print $0;}
$1=="age"{print $0}
[zpxu@node102 ~]$ awk -f d data
name naughty
25 shandong
age 14
getline从整体上来说,应这么理解它的用法:
的返回结果是隔行的。
多行或多列的删除
多行
1 | [zpxu@node102 ~]$ cat 1.txt |
多列
1 | [zpxu@node102 ~]$ cat data |
参考资料
Linux awk 命令
awk函数+数组+多文件处理