|
GNU awk
AWK:Aho,Weinberger,Kernighan
GNU awk --> gawk
#ll `which awk`
/usr/bin/awk -> gawk
报表生成器,格式化文本输出;
#man awk
pattern scanning and processing language.
模式扫描和处理语言;
基本用法:
awk [option] 'program' file
program: PATTERN{ACTION STATEMENTS}
语句之间用分号分隔;
print, printf
选项:
-F,--field-separator:指定输入分隔符;the value of the FS predefined variable.可以不指定,则默认以空白为分隔符;
-v var=val:定义变量;
awk后续的所有动作都是以单引号括住的,可以说是awk的固定用法;单引号里面不能再用单引号;
文件中的行称为记录(Records);
文件中的字段称为(Fields);
awk工作流程:
第一步:执行BEGIN{}中的语句;
第二步:逐行扫描和处理文件;
第三步:扫描处理完文件之后,执行END{}中的语句;
print命令:
print item1,item2,...
(1)逗号分隔符;输出格式以空白分隔;
(2)输出的item可以是字符串,数值,字段,变量,或awk的表达式;
(3)如果省略item,相当于打印整行print $0;
#tail -5 /etc/fstab | awk '{print $2$4}' #不加逗号时,输出字段会连在一起;
#tail -5 /etc/fstab | awk '{print $2 $4}'
swapdefaults
/media/cdromdefaults
/homedefaults,usrquota,grpquota
/mnt/lvmdefaults
/mnt/btreedefaults
#tail -5 /etc/fstab | awk '{print "hello",$2,$4,6}' #数字被当作字符输出;运算时依然是数值;
hello swap defaults 6
hello /media/cdrom defaults 6
hello /home defaults,usrquota,grpquota 6
hello /mnt/lvm defaults 6
hello /mnt/btree defaults 6
#tail -5 /etc/fstab | awk '{print "hello:$1"}' #$1放在引号里面不会被解析,被当作字符串输出;
hello:$1
hello:$1
hello:$1
hello:$1
hello:$1
#tail -5 /etc/fstab | awk '{print "hello:"$1}'
hello:UUID=4b27a61a-4111-4d30-96ac-93cff82b227e
hello:/dev/sr0
hello:/dev/sda6
hello:UUID="6b77b0f3-5a0e-4b28-924c-139f6334da5b"
hello:UUID=3a3edcd8-a24f-414a-ace6-9952a3ca4891
#tail -5 /etc/fstab | awk '{print}' #打印整行;
UUID=4b27a61a-4111-4d30-96ac-93cff82b227e swap swap defaults 0 0
/dev/sr0 /media/cdrom iso9660 defaults 0 0
/dev/sda6 /home ext4 defaults,usrquota,grpquota 0 0
UUID="6b77b0f3-5a0e-4b28-924c-139f6334da5b" /mnt/lvm ext4 defaults 0 0
UUID=3a3edcd8-a24f-414a-ace6-9952a3ca4891 /mnt/btree btrfs defaults 0 0
#tail -5 /etc/fstab | awk '{print ""}' #显示空白;这里没有指定输出文件的字段;
变量
内建变量,Built-in Variables
FS:The input field separator, a space by default. 输入时的字段分隔符;与"-F"作用相同;
#awk -v FS=':' '{print $1}' /etc/passwd |head -3
root
bin
daemon
#awk -v FS=: '{print $1}' /etc/passwd #FS后面的引号可省略;
#awk -F: '{print $1}' /etc/passwd
OFS:The output field separator, a space by default. 输出时的字段分隔符;
#awk -v FS=: -v OFS=: '{print $1,$3,$7}' /etc/passwd | head -5
root:0:/bin/bash
bin:1:/sbin/nologin
daemon:2:/sbin/nologin
adm:3:/sbin/nologin
lp:4:/sbin/nologin
RS:The input record separator, by default a newline. 输入时的行分隔符,换行符;
#awk -v RS=' ' '{print}' /etc/passwd #指定以space为换行符,即有空白的地方会换行;打印时原有的换行符依然会换行;
#vim file2
a:b c:d
x:y:z
#awk -v RS=':' '{print $1}' file2
a
b
d
y
z
#awk -v RS=':' '{print $2}' file2 #这里处理d x时,把原有的换行符当作空白处理了;
c
x
ORS:The output record separator, by default a newline. 输出时的行分隔符,换行符;
#awk -v RS=' ' -v ORS='#' '{print}' /etc/passwd | tail -5 #指定以#为输出换行符,实际结果是空白换行符被替换为#输出,原有的换行符依然会换行;
radvd:x:75:75:radvd#user:/:/sbin/nologin
sssd:x:983:978:User#for#sssd:/:/sbin/nologin
gdm:x:42:42::/var/lib/gdm:/sbin/nologin
gnome-initial-setup:x:982:977::/run/gnome-initial-setup/:/sbin/nologin
named:x:25:25:Named:/var/named:/sbin/nologin
NF:The number of fields in the current input record. 每一行的字段数量;
#awk '{print NF}' /etc/fstab #显示字段数量;
#awk '{print $NF}' /etc/fstab #$NF显示最后一个字段;
NR:The total number of input records seen so far. 读取的总行数;
#awk '{print NR}' /etc/fstab #显示每一行的行号;
#awk '{print NR}' /etc/fstab /etc/issue #跟多个文件时,会连在一起连续编号;
FNR:The input record number in the current input file. 对每个文件单独显示行号;
#awk '{print FNR}' /etc/fstab /etc/issue #两个文件单独编号;
FILENAME:The name of the current input file. 当前读取的文件的文件名;
#awk '{print FILENAME}' /etc/fstab /etc/issue #每读取一行,打印一次当前读取的文件的文件名;
ARGC:The number of command line arguments.does not include options to gawk, or the program source. 命令行参数的数量;不包括awk的选项和program;
#awk '{print ARGC}' /etc/fstab /etc/issue
#awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
ARGV:Array of command line arguments. The array is indexed from 0 to ARGC-1. 数组,命令行参数的数组;
#awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue
#awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue
#awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue
自定义变量
变量名区分字符大小写;
(1)-v var=value;
#awk -v test='hello awk' '{print test}' /etc/fstab
#awk -v test='hello awk' 'BEGIN{print test}' /etc/fstab
(2)在program中定义;
#awk 'BEGIN{test="hello gawk"; print test}' #BEGIN模式,不对文件进行处理;
printf命令:
格式化输出:
format and print data.
#yum provides printf
#rpm -ql coreutils
printf FORMAT(格式符),item1,item2,...
(1)FORMAT必须给出;
(2)printf不会自动换行,需要手动指定换行符,\n;
(3)FORMAT中需要分别为后面的每个item指定一个格式化符号;
(4)printf不是管道命令;
格式符:
%c:显示字符的ASCII码;
%d:,%i:显示十进制整数;
%e,%E:科学计数法显示数值;
%f:浮点数;
%g,%G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%:显示%自身;
#awk -F: '{printf "%s\n",$1}' /etc/passwd #格式符需要用引号引起来;
#awk -F: '{printf "username: %s\n",$1}' /etc/passwd
#awk -F: '{printf "username: %s\n, uid: %d\n",$1,$3}' /etc/passwd #这里打印多个字段时,$1对应第一串格式,$3对应第二串格式;
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个数字表示小数点后的精度;
%3.1f
-:表示左对齐;默认是右对齐;
#awk -F: '{printf "username: %-20s uid: %d\n",$1,$3}' /etc/passwd #指定15个字符的宽度显示$1,并左对齐;
username: root uid: 0
username: bin uid: 1
username: daemon uid: 2
#awk -F: '{printf "username: %20s uid: %d\n",$1,$3}' /etc/passwd
username: root uid: 0
username: bin uid: 1
username: daemon uid: 2
+:显示数值的正负符号;
%+d
#awk -F: '{printf "%-20s | %+10d\n",$1,$3}' /etc/passwd
操作符:
算术运算操作符:
x+y, x-y, x*y, x/y, x^y, x%y
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
比较操作符:
>, =, |
|