linux awk 命令笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lcharon/article/details/77259592

推荐awk学习系列
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-1/index.html
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-2/index.html
https://www.ibm.com/developerworks/cn/linux/shell/awk/awk-3/index.html
工具书
https://book.saubcy.com/AwkInAction/section_1/chapter_2_1.html

1 调用awk方式

1.命令行方式
awk [-F field-separator] ‘commands’ input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk

3.将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。

2 基本命令

2.1 行匹配语句 awk ” 只能用单引号

awk '{[pattern] action}' {filenames}  


test.sh文件
将文件按照’\t’或者’ ‘分割,输出第一列和第四列的内容

#!/bin/bash
awk '{print $1,$4}'

执行

chmod +x test.sh
cat b | ./test.sh

结果 输出b文件中每行的第一列和第四列

2.2 指定分隔符关键字 -F

脚本文件

#!/bin/bash
awk -F, '{print $1,$4}'

指定分隔符为’,’

指定多个分隔符 -F ‘[]’
脚本文件

#!/bin/bash
awk -F '[\t,]' '{print $1}'

先按照’\t’切分,再按照’,’切分

扫描二维码关注公众号,回复: 4610735 查看本文章

2.3 设置变量

awk -v设置变量

脚本文件

#/bin/bash
awk -va=1 -vb=s '{print $1,$1+a,$1b}'

$1+a是计算第一列与变量a的和,如果$1为字符串,则只返回变量a的数值,$1b是字符串拼接,将$1与变量a的内容链接起来

2.4 筛选匹配

脚本文件

#/bin/bash
awk  '$1>3 && ($3 == "d" || $3 == "e") { print $0 }'

类c模式,左边为条件,右边为满足条件的操作,这里是满足条件输出当前行

2.5 正则

# 输出第二列包含 "th",并打印第二列与第四列
$ awk '$2 ~ /th/ {print $2,$4}' log.txt
# 输出包含"re" 的行
$ awk '/re/ ' log.txt
# 忽略大小写
$ awk 'BEGIN{IGNORECASE=1} /this/' log.txt
# 模式取反
$ awk '$2 !~ /th/ {print $2,$4}' log.txt
$cat a
1.021 33
1#.ll   44
2.53 6
ss    7
awk 'BEGIN{total = 0;len = 0} {if($1~/^[0-9]+\.[0-9]*/){total += $1; len++}} END{print total/len}' a
$1~/^[0-9]+\.[0-9]*/表示$1与“/ /”里面的正则表达式进行匹配,若匹配,则total加上$1,且len自增,即数目加1.“^[0-9]+\.[0-9]*”是个正则表达式,“^[0-9]”表示以数字开头,“\.”是转义的意思,表示“.”为小数点的意思。“[0-9]*”表示0个或多个数字

3 awk脚本

关于awk脚本,有两个关键词BEGIN和END。

  • BEGIN{ 这里面放的是执行前的语句 }
  • END {这里面放的是处理完所有的行后要执行的语句 }
  • {这里面放的是处理每一行时要执行的语句}

文件

$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

awk脚本

$ cat cal.awk
#!/bin/awk -f
#运行前
BEGIN {
    math = 0
    english = 0
    computer = 0

    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

执行

awk -f cal.awd score

结果

NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
---------------------------------------------
  TOTAL:       319      393      350
AVERAGE:     63.80    78.60    70.00

4 其他

awk、sed、grep更适合的方向:

  • grep 更适合单纯的查找或匹配文本
  • sed 更适合编辑匹配到的文本
  • awk 更适合格式化文本,对文本进行较复杂格式处理

关于awk内建变量

  • 解释一下变量:
  • 变量:分为内置变量和自定义变量;输入分隔符FS和输出分隔符OFS都属于内置变量。
  • 内置变量就是awk预定义好的、内置在awk内部的变量,而自定义变量就是用户定义的变量。

    FS:输入字段分隔符, 默认为空白字符
    OFS:输出字段分隔符, 默认为空白字符
    RS:输入记录分隔符(输入换行符), 指定输入时的换行符
    ORS:输出记录分隔符(输出换行符),输出时用指定符号代替换行符
    NF:当前行的字段的个数(即当前行被分割成了几列)
    NR:行号,当前处理的文本行的行号。
    FNR:各文件分别计数的行号
    ARGC:命令行参数的个数
    ARGV:数组,保存的是命令行所给定的各参数
    自定义变量的方法
    方法一:-v varname=value ,变量名区分字符大小写。

引用 http://www.runoob.com/linux/linux-comm-awk.html

5 笔记

  • 执行awk脚本传参
awk -f test.awk a="test" filename #入参a,数据类型为string
awk -f test.awk a=1 filename #入参a,数据类型为数字
# 在脚本呢中直接用a访问
  • awk脚本中的数组
#awk 遇到第一个赋值语句时,它将创建 myarray
myarray[1]="jim"
myarray[2]=456
#遍历数组
for ( x in myarray ) {
    print myarray[x]
}

注意:每次赋值以后都循环一次循环代码。虽然这是一个非常方便的 awk 功能,但它有一个缺点 – 当 awk 在数组下标之间轮转时,它不会依照任何特定的顺序。
所以输出可能是

jim
456

也可能是

456
jim

awk的性质: 数组下标字符串化
所以awk可以当作map来使用

myarr["name"]="Mr. Whipple"
print myarr["name"]

同样的
可以判断key是否在array中

if ( 1 in fooarray ) {
    print "Ayep!  It's there."
} else {
    print "Nope!  Can't find it."
}

删除元素的操作

delete fooarray[1]

猜你喜欢

转载自blog.csdn.net/Lcharon/article/details/77259592
今日推荐