Shell中awk的认识与了解
awk工作原理
awk是逐行读取文本,默认通过空格和tab键分隔,将分隔所得的各个字段保存到内建变量中,按模式或条件执行编辑命令。
sed倾向于整行的文本处理,awk倾向于将一行划分为多个字段再进行处理。实际上awk读入方式也是逐行读取,执行结果则通过print的功能将字段数据打印显示,而在awk中可用(&&,||,!,+,-,*,/,%取余,^乘方)
二、语法格式
1、格式
格式1:前置命令 | awk [选项] ‘条件{编辑指令}'
格式2:awk [选项] ‘条件{编辑指令}' 文件...
编辑指令如果包含多条语句时,可以用分号分隔,处理文本时,若未指定分隔符,则默认将空格、制表符等作为分隔符。print是最常见的指令。
2、选项
-F:指定分隔符,可省略(默认空格或Tab位)
-V:调用外部Shell变量 variable
awk的内置变量
变量 | 用途 | 示例 |
FS | 保存或设置字段分隔符,如FS=”:” |
|
$n | 指定分隔的第n个字段,如$1、$3分别表示第1、第3列 | awk -F: '{print "用户名:"$1}' /etc/passwd awk -F “:” '{print "第2列是:",$2}' a.txt 输出第1、7个字段# awk -F: '{print $1","$7}' a.txt # awk -F ":" '{print $1","$7}' a.txt 分隔符用:或/ # awk -F [:/] '{print $1","$7}' a.txt # free |awk '/Mem/{print $1,$2}' 输出文件的第1、2列:free |awk '{print $1,$2}' 查看root密码:awk -F: '/root/{print $2}' /etc/shadow 输出第1、3、12字段:uname -a | awk '{print $1,$3,$12}' |
$0 | 当前读入的整行文本内容 |
|
NF | 记录当前处理行的字段个数(列数)
| 输出最后一列$NF:awk '{print “Last:”$NF}' a.txt 输出倒数第二列:awk '{print “Last:”$(NF-1)}' a.txt |
NR | 记录当前已读入行的数量(行数) | awk '{print NR}' a.txt |
FNR | 当前行在源文件中的行号 | awk '{print “第”FNR”行”,“有“NF”列”}' a.txt b.txt |
awk 'END {print NR}' temp 在最后打印已读记录条数
awk '{print NF,NR,$0} END {print FILENAME}' temp
awk '{if (NR>0 && $4~/Brown/) print $0}' temp 至少存在一条记录且包含Brown
NF的另一用法: echo $PWD | awk -F/ '{print $NF}' 显示当前目录名
awk的操作符使用
awk中使用操作符,基本表达式可以划分成数字型、字符串型、变量型、域及数组元素
### 设置输入域到变量名:
awk '{name=$1;six=$3; if (six=="man") print name " is " six}' temp
### 域值比较操作:
awk 'BEGIN {BASE="27"} {if ($4<BASE) print $0}' temp
### 修改数值域取值:(原输入文件不会被改变)
awk '{if ($1=="asima") $6=$6-1;print $1,$6,$7}' temp
### 修改文本域:
awk '{if ($1=="asima) ($1=="desc");print $1}' temp
### 只显示修改记录:(只显示所需要的,区别上一条命令,注意{})
awk '{if ($1=="asima) {$1=="desc";print$1}}' temp
### 创建新的输出域:
awk '{$4=$3-$2; print $4}' temp
### 统计列值:
awk '(tot+=$3);END {print tot}' temp ### 会显示每列的内容
awk '{(tot+=$3)};END {print tot}' temp ### 只显示最后的结果
### 文件长度相加:
ls -l|awk '/^[^d]/ {print $9"\t"$5} {tot+=$5} END{print "totKB:" tot}'
### 只列出文件名:
ls -l|awk '{print $9}' 常规情况文件名是第9域
awk内置字符串函数的认识基础实例
gsub(r,s) 在整个$0中用s替代r
awk 'gsub(/name/,"xingming") {print $0}' temp
gsub(r,s,t) 在整个t中用s替代r
index(s,t) 返回s中字符串t的第一位置
awk 'BEGIN {print index("Sunny","ny")}' temp 返回4
length(s) 返回s的长度
match(s,r) 测试s是否包含匹配r的字符串
awk '$1=="J.Lulu" {print match($1,"u")}' temp 返回4
split(s,a,fs) 在fs上将s分成序列a
awk 'BEGIN {print split("12#345#6789",myarray,"#")"'
awk的小扩展
### 向一行awk命令传值:
awk '{if ($5<AGE) print $0}' AGE=10 temp
who | awk '{if ($1==user) print $1 " are in " $2 ' user=$LOGNAME 使用环境变量