awk入门学习笔记


零、awk的介绍
awk是Linux及Unix操作系统中非常优秀的数据及文本处理工具,它是一种编程语言。
主要用途是自动化运维和文本处理
一、awk基本语法
1、命令行格式:
awk -F' ' '{print $1}' pets.txt
awk -F '{print $1}' pets.txt(因为默认是空格,所以这种情况和上面的等效,但是我在尝试的时候会报错)
-F后面是指定的分隔符,:或者' '

awk 'BEGIN{FS=" "}{print $1}' pets.txt
2、文本格式:
#!/usr/bin/awk
BEGIN{ FS=":"}
{print $1}

二、awk的变量
1、常用内置变量
$0 当前所有字段
$1~$n 当前第n个字段
FS 分隔符(默认为空格)
NF 字段个数
NR 行号
RS 输入记录的分隔符(默认为空格)

2、RS是指定的换行符,系统默认是\n进行换行,但是如果我们不希望使用\n而是使用自定义的换行符来进行分行,
那么只需要更改RS参数的值即可
awk 'BEGIN{RS=" "}{print $0}' pets.txt

3、NF是列数,如果我们需要打印每一行按照我们指定的分隔方法有多少列,可以用如下命令调用
awk -F":" '{print NF}' /etc/passwd----------->输出若干列7,代表文件中每一行中以“:”作为分隔符都有7列。

4、NR是行号,如果我们需要给文件的每一行加上一个固定的行号格式,例如 "1 : "的形式,可以使用以下语句
awk -F' ' '{print NR" : " $0}' pets.txt

5、调用外部变量
awk -v host=$HOSTNAME 'BEGIN{print host}'
也可以自己定义变量名
awk -v host="host" 'BEGIN{print host}'

三、awk的操作符
关系操作符:<、>、<=、>=、==、!=、~ 、!~
1、按照指定要求匹配内容,如果我们需要匹配passwd文件中第七列是以/bin开头的那些行,可以如下表示
awk -F: '$7 ~ /^\/bin/{print $0}' /etc/passwd
冒号分隔 ~代表匹配 ^代表字符串起始标志,匹配内容是/bin(注意后面还要带一个/,否则会报错)
那如果我们需要不匹配/bin开头的行,只需要将~改成!~即可。
上述代码也可以用变量的形式来替代
awk -F: -v reg='^/bin.*' '$7 ~ reg {print $0}' /etc/passwd
用一个正则表达式 reg来代替^/bin.*,然后再匹配第七列符合正则表达式的行并且返回
2、print与printf
如果要打印 /etc/passwd 中的“第一列 : 第二列”这种形式的输出,可以如下操作:
awk -F: '{print $1" : "$2}' /etc/passwd
如果要实现上述功能,可以用printf操作如下:
awk -F: '{printf("%s : %s\n",$1,$2)}' /etc/passwd

四、awk的流程控制
1、条件语句
格式:if(expression) action1;[else action2]
输入一串数字,单数打印no,双数打印yes,可以如下表示
seq 10|awk '{if($0%2==0){print "ok"}else {print "no"}}'
对文件操作,如果/etc/passwd最后一列是以/bin/bash结尾的,那么就打印整行的内容
awk -F: '{if($NF=="/bin/bash"){print $0}}' /etc/passwd
同样可以不写if语句加上一次判断实现一样的功能
awk -F: '$NF=="/bin/bash" {print $0}' /etc/passwd
2、循环语句
格式:while(condition) action
例:如果我们需要给每个按照分隔符分开的列加上一个列号,如 1:第1列的内容 2:第二列的内容,.......
awk -F: '{i=1;while(i<=NF){printf(" %d:%s",i,$i);i++}{print " "}}' /etc/passwd
同样也能用for循环完成同样的功能
awk -F: '{for(i=1;i<=NF;i++){printf(" %d:%s",i,$i)}{print " "}}' /etc/passwd
例:需要统计最后一列的词出现的频数
awk -F: '{a[$NF]++}END{for(i in a){print i":"a[i]}}' /etc/passwd

3、awk数组
定义一个数组并且打印它
awk 'BEGIN{a[5]="Jack";a["name"]="Lilei";print a[5],a["name"]}'
同样可以用循环来遍历
awk_sed$ awk 'BEGIN{a[5]="Jack";a["name"]="Lilei";for(i in a)print i":"a[i]}'

netstat -an | awk '/^tcp/{state[$NF]++}END{for(key in state){print key"\t"state[key]}}'
五、awk函数
1、算术函数
awk的算术函数、字符串函数
int(x) 返回x的整数部分的值
sqrt(x) 返回x的平方根
rand() 返回伪随机数r,其中0<=r<1
sand(x) 建立rand()新的种子数。如果没有指定就用当天的时间。
随机数示例:
awk 'BEGIN{print rand();srand();print rand()}'
2、字符串函数
sub(),gsub() 替换函数
index(s,t) 返回子串t在字符串s中的位置,如没有则返回0。
length(s) 返回字符串长度,当没有给出s时,返回$0的长度。
match(s,r) 如果正则表达式r在s中匹配到,则返回出现的起始位置,否则返回0
split(s,a,sep) 使用sep将字符串s分解到数组a中。默认sep为FS。
tolower(s) 将字符串s中的所有大写字符转换为小写。
toupper(s) 将字符串s中的所有小写字符转换为大写。
例:替换字符串中的某个单词。将world换成China,
echo "hello world world" | awk '{sub("world","China");print $0}'
输出: hello China world

上例只是替换了一个world,用gsub可以将所有的都进行替换
echo "hello world world" | awk '{gsub("world","China");print $0}'
输出:hello China China

查找子串的位置
echo "hello world world" | awk '{print index($0,"world")}'

用指定分隔符分隔字符串
echo "00-11-22-33-44" |awk '{split($0,a,"-");for(i in a){print i":"a[i]}}'

3、自定义函数
自定义加法
awk 'function sum(n,m) {total=n+m;return total} BEGIN{print sum(1,2)}'

六、一些常用的操作
1、获取本机的ip地址
ifconfig eth0 | awk -F':| +' '/inet addr:/{print $4}'
2、统计网络连接数
netstat -an | awk '/^tcp/{state[$NF]++}END{for(key in state){print key"\t"state[key]}}' | column -t
3、在做训练集的时候需要统计不同类别的分布的时候,可以有如下办法(假设label放在最后,个人习惯):
cat test.txt | awk '{count[$NF]++}END{for(key in count){print key"\t"count[key]}}' | sort -k2 -n -r
或者
awk '{print $NF}' test.txt | sort | uniq -c | sort -nr
test.txt的最后一列是label,统计它的label
4、将文件最后一列去掉
awk '{$NF="";print $0 >>"test.txt"}' 51job.txt




你可能感兴趣的:(unix,编程语言,awk)