awk命令

awk:报告生成器,格式化文本输出

AWK : Aho,weinberger,Kernighan —-》 New AWK ,NAWK
GNU awk ,gawk

gawk —pattern
awk的操作,
一次读取一行文本,通过输入分隔符进行切片。
内建的变量,$1 $2 $3 依次多个

awk循环功能: 本身自己可以进行行间循环。
在字段间完成循环机制进行操作。
为了实现文本的格式化输出。
#tail 5 /etc/fatab|awk ‘{printf $2,$4}’

1,print
print item1,item2,….
要点: 1, 逗号分隔符
2, 输出的各item可以字符串,也可以输出自定义的字符串。也可以数值: 当前记录的字段,变量或者awk
的表达式

3, 打印整行内容显示。 省略item ,相当于 print $0

显示空白
tail 5 /etc/fstab |awk ‘{print “ “}’

变量:
2.1 内建变量

FS : input field seperator,默认为空白字符
OFS:output field seperator,默认为空白字符
RS: input record seperator, 输入时的换行符。
ORS: output record seperator ,输出时的换行符。
NF: number of field,字段数量
{print NF}, 显示每行字段数量
{print $NF}: 获取到字段的值。
NR : 打印行数。
FNR:各文件分别计数 :行数。
FILENAME :当前文件名
ARGC:命令行参数的个数
ARGV:数组 保持的是命令行所给定的各参数

AWK工作流程:逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行用户想要到的操作。
AWK基本结构有模式匹配和处理过程(即处理动作)组成。
pattern {action}
awk读取文件内容的每一行时,将对比该行是否与给定的模式相匹配,匹配则执行处理过程,否则对该行不处理。

1.运算**
awk 还允许我们执行整数和浮点运算。通过使用数学表达式,可以很方便地编写计算文件中空白行数量的脚本。以下就是这样一个脚本:
awk ‘BEGIN { x=0 }/^$/ { x=x+1 }END { print “I found “ x “ blank lines. “ }’ 文件名
在 BEGIN 块中,将整数变量 x 初始化成零。然后,awk 每次遇到空白行时,awk 将执行 x=x+1 语句,递增 x。处理完所有行之后,执行 END 块,awk 将打印出最终摘要,指出它找到的空白行数量。

awk 的优点之一就是“简单和字符串化”。我认为 awk 变量“字符串化”是因为所有 awk 变量在内部都是按字符串形式存储的。同时,awk 变量是“简单的”,因为可以对它执行数学操作,如果想要对每个输入行的第一个字段乘方并加一,可以使用以下脚本:
awk { print ($1^2)+1 } 文件
awk 在对数学表达式求值时会将该变量当作数字零处理
awk 的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除,awk 还允许使用前面演示过的指数运算符 “^”、模(余数)运算符 “%” 和其它许多从 C 语言中借入的易于使用的赋值操作符。
这些运算符包括前后加减(i++、—foo)、加/减/乘/除赋值运算符( a+=3、b*=2、c/=2.2、d-=6.2)。不仅如此 — 我们还有易于使用的模/指数赋值运算符(a^=2、b%=4)。

2. FS 字段分隔符
FS 值并没有被限制为单一字符;可以通过指定任意长度的字符模式,将它设置成规则表达式。如果正在处理由一个或多个 tab 分隔的字段,您可能希望按以下方式设置 FS:
cat file
a b
a c

awk -vFS=”\t+” ‘{print $2}’ file
以上示例中,我们使用特殊 “+” 规则表达式字符,它表示“一个或多个前一字符”。
如果字段由空格分隔(一个或多个空格或 tab),您可能想要将 FS 设置成以下规则表达式:
awk FS=”[[:space:]+]” ‘{print $2}’ file

3.NF变量(字段总数)
cat file
hello everyone!!
This is egg!!
可以使用 NF 变量来只显示某些输入行:
awk ‘NF == 3 { print “this particular record has three fields: “ $0 }’ file
当然,也可以在条件语句中使用 NF 变量,如下:
awk ‘{if ( NF > 2 ) {print $1 “ “ $2 “:” $3}}’ file

4.NR变量(当前行数**)**
例:
awk ‘{if(NR>10)print “OK,now for the real information!”}’ file
如果行数大于10 就打印。。。。

5.RT变量(就是指定的那个分隔符**)**
例:
echo “111 222|333 444|555 666” |awk ‘BEGIN{RS=”|”}{print $0,RT}’
RT即是分隔符 |

6.RS变量(记录分隔符,默认分隔符为\n)
例如:
echo “111 222|333 444|555 666”|awk ‘BEGIN{RS=”|”}{print $0,RT}’
输出结果为:
111 222 |
333 444 |
555 666

也可为正则表达式
echo “111 222a333 444b555 666”|awk ‘BEGIN{RS=”[a-z]+”}{print $1,RS,RT}’
结果为:

  1. 111 [a-z]+ a
  2. 333 [a-z]+ b
  3. 555 [a-z]+

注:RS为空时,即RS=”” awk会自动以多行作为分隔符,即\n\n….

7.ORS变量(记录输出分隔符,默认为\n**
把ORS看成是RS的反过程,更易于理解。**

  1. [zhangy@localhost test]$ awk ‘BEGIN{ORS=”\n”}{print $0}’ test1 //awk ‘{print $0}’ test1二者是一样的
  2. 111 222
  3. 333 444
  4. 555 666
  5. [zhangy@localhost test]$ awk ‘BEGIN{ORS=”|”}{print $0}’ test1
  6. 111 222|333 444|555 666|


8.FS变量与OFS变量**
1.FS指定列分隔符

  1. [zhangy@localhost test]$ echo “111|222|333”|awk ‘{print $1}’
  2. 111|222|333
  3. [zhangy@localhost test]$ echo “111|222|333”|awk ‘BEGIN{FS=”|”}{print $1}’
  4. 111

2.FS也可用正则

  1. [zhangy@localhost test]$ echo “111||222|333”|awk ‘BEGIN{FS=”[|]+”}{print $1}’
  2. 111

3.FS为空的时候

  1. [zhangy@localhost test]$ echo “111|222|333”|awk ‘BEGIN{FS=””}{NF++;print $0}’
  2. 1 1 1 | 2 2 2 | 3 3 3

当FS为空的时候,awk会把一行中的每个字符,当成一列来处理
4.RS被设定成非\n时,\n会成FS分割符中的一个

  1. [zhangy@localhost test]$ cat test1
  2. 111 222
  3. 333 444
  4. 555 666
  5. [zhangy@localhost test]$ awk ‘BEGIN{RS=”444”;}{print $2,$3}’ test1
  6. 222 333
  7. 666

222和333之间是有一个\n的,当RS设定成444后,222和333被认定成同一行的二列了,其实按常规思想是二行的一列才对

5.OFS列**输出分隔符**

  1. [zhangy@localhost test]$ awk ‘BEGIN{OFS=”|”;}{print $1,$2}’ test1
  2. 111|222
  3. 333|444
  4. 555|666
  5. [zhangy@localhost test]$ awk ‘BEGIN{OFS=”|”;}{print $1 OFS $2}’ test1
  6. 111|222
  7. 333|444
  8. 555|666

test1只有二列,如果100列,都写出来太麻烦了吧。

  1. [zhangy@localhost test]$ awk ‘BEGIN{OFS=”|”;}{print $0}’ test1
  2. 111 222
  3. 333 444
  4. 555 666
  5. [zhangy@localhost test]$ awk ‘BEGIN{OFS=”|”;}{NF=NF;print $0}’ test1
  6. 111|222
  7. 333|444
  8. 555|666

自定义
-v var=value
变量名区分字符大小写

(2) 在program中直接定义。
###显示一次hello gawk 不需要有文件
#awk -v test=’hello gawk’ ‘BEGIN{print test}’
###显示多次 hello gawk ,需要文件,任意文件
#awk -v test=”hello gawk” ‘{print test}’ /etc/passwd
#awk ‘BEGIN {print test}’

printf命令
格式化输出:
prinf FORMAT,item1,item2,item3,….
FORMAT 是必须要给出; 它不会自动换行。 换行的话,需要给出显式换行控制符,\n
FORMAT 需要分别为后面的每个item指定一个格式化符号。
格式符:
%c : 显示字符的 ASCII码
%d , %i显示十进制整数
%e : %E 科学计数法数值显示。
%g : %G 浮点形式显示
%s : 显示字符串。

#awk F:’{printf %c,$1}’ /etc/passwd
awk F:’{printf “hello %c,%s” $1,$2}’ /etc/passwd

修饰符:
#[.#0]:第一个数字控制显示的宽度: 第二个#表示小数点的精度
%3.1f
-:左对齐
+:显示数值的符号。

操作符:
算术操作符:
x+y x-y x*y x/y x^y x%y
-x
+x 转换为数值;

字符串操作符: 没有符号的操作符。字符串连接之一。

赋值操作符
= += -= = /= %= ^=

比较操作符
>, >=,<=,!= ==
*模式匹配符

~

逻辑操作符
&& || !

函数调用
function_name(argu1,argu2,argu3,….)

条件表达式
selector ? if-true-expression:if-false-expression
###通过? 获取/etc/passwd 哪些用户属于管理员账号,哪些是属于普通账户。
#awk -F: ‘{$3>=1000?usertype=”common user”:usertype=”sysadmin or sysuser”;printf “%15s:%-s\n” ,$1,usertype}’ /etc/passwd

PATTERN 类似 定界符功能。
(1)空模式,匹配每一行。
(2) /regular expression/ : 仅处理能够被此处的模式匹配到的行。
(3) relational expression: 关系表达式
结果有真,有假,结果为真,才会被处理: 真:结果为非0,非空字符串:

awk -F: ‘$NF==”/bin/bash” {print $1,$NF}’ /etc/passwd

(4) line ranges:行范围
startline,endline: /pat1/,/pat2/
注意: 不支持直接给出数字的格式
#awk -F: ‘(NR>=2&&NR<=10){print $1}’ /etc/passwd
(5) BEGIN END模式
BEIGIN{} : 仅在开始处理文件中的文本之前执行一次;
END{} : 仅在文本处理完成之后执行一次:
awk -F: ‘BEGIN{print “username urd \n—————“}print{$1,$3}’
常用的action
(1) expression表达式
(2) control statement 控制语句
(3)compound statements: 组合语句
(4) input statemnet 输入语句
(5) output statments 输出语句

控制语句:
if(condtion) {statments}
if(condtion) {statments} else {statements}
while(condtion) {statments}
do {statements} while(conditon)
for(expr1,expr2,expr3){statements}
break
continue
delete array[index]
delete array
exit

#UID是否大于1000,确认用户属于什么类型用户
awk -F: '{$3>=1000?usertype="common user":usertype="sysadmin or sysuser";printf "%15s:%-10s\n",$1,usertype}' /etc/passwd

#获取文件内的第一行和第三行,同时分别显示列表名
awk -F: 'BEGIN{print "username uid \n----------"}print{$1,$3}'END{print "helo"} /etc/passwd

例子
1#遍历文件中以空格开头的任意字符跟save并且字符串长度大于10的字符及其对应的字符长度
awk '/^[[:space:]]*save/{for(i=1;i<=NF;i++) {if(length($i)>10) {print $i,length($i)}}}' /etc/grub2.cfg