阅读(1393) (19)

AWK 备忘单

2021-08-30 16:21:53 更新

AWK 备忘单

这是 GNU awk 的 一页快速参考备忘单,其中涵盖了常用的 awk 表达式和命令。

开始

尝试一下

$ awk -F: '{print $1, $NF}' /etc/passwd
-F:冒号作为分隔符
{...}awk 程序
print打印当前记录
$1第一个字段
$NF最后一个字段
/etc/passwd输入数据文件

awk 程序

BEGIN          {<initializations>} 
   <pattern 1> {<program actions>} 
   <pattern 2> {<program actions>} 
   ...
END            {< final actions >}

例子

awk '
    BEGIN { print "n>>>Start" }
    !/(login|shutdown)/ { print NR, $0 }
    END { print "<<<ENDn" }
' /etc/passwd

变量

          $1      $2/$(NF-1)    $3/$NF
           ▼          ▼           ▼ 
        ┌──────┬──────────────┬───────┐
$0/NR ▶ │  ID  │  WEBSITE     │  URI  │
        ├──────┼──────────────┼───────┤
$0/NR ▶ │  1   │  quickref.me │  awk  │
        ├──────┼──────────────┼───────┤
$0/NR ▶ │  2   │  google.com  │  25   │
        └──────┴──────────────┴───────┘
# First and last field
awk -F: '{print $1,$NF}' /etc/passwd

# With line number
awk -F: '{print NR, $0}' /etc/passwd

# Second last field
awk -F: '{print $(NF-1)}' /etc/passwd

# Custom string 
awk -F: '{print $1 "=" $6}' /etc/passwd

请参阅:变量

awk 程序示例

awk 'BEGIN {print "hello world"}'        # Prints "hello world"
awk -F: '{print $1}' /etc/passwd         # -F: Specify field separator

# /pattern/ Execute actions only for matched pattern
awk -F: '/root/ {print $1}' /etc/passwd                     

# BEGIN block is executed once at the start
awk -F: 'BEGIN { print "uid"} { print $1 }' /etc/passwd     

# END block is executed once at the end
awk -F: '{print $1} END { print "-done-"}' /etc/passwd

条件

awk '{if ($3>30) print $1}' /etc/passwd

见:条件

生成 1000 个空格

awk 'BEGIN{
    while (a++ < 1000)
        s=s " ";
    print s
}'

请参阅:循环

数组

awk 'BEGIN {
   fruits["mango"] = "yellow";
   fruits["orange"] = "orange"
   print fruits["orange"] 
   print fruits["mango"]
}'

请参阅:数组

函数

# => 5
awk 'BEGIN{print length("hello")}'
# => HELLO
awk 'BEGIN{print toupper("hello")}'
# => hel
awk 'BEGIN{print substr("hello", 1, 3)}'

请参阅:函数

awk 变量

内置变量

$0全线
$1, $2...$NF第一个,第二个……最后一个字段
NR已经处理过的总记录数目,或者说行号(不一定是一个文件,可能是多个)
NF一条记录的字段的数目
OFS当与输出上的 ​FS​, 默认是以一个空格字符作为输出分隔符的
FS读取并解析输入文件中的每一行时,默认按照空格分隔为字段变量,$1,$2...等
ORS相当于输出的 ​RS​。 每条记录在输出时候会用分隔符隔开,
RS定义了一行记录。读取文件时,默认将一行作为一条记录。
FILENAME文件名

表达式

$1 == "root"第一个字段等于根
{print $(NF-1)}倒数第二个字段
NR!=1{print $0}从第 2 个记录
NR > 3从第 4 记录
NR == 1第一条记录
END{print NR}总记录
BEGIN{print OFMT}输出格式
{print NR, $0}电话号码
{print NR " " $0}行号(选项卡)
{$1 = NR; print}用行号替换第 1 个字段
$NF > 4最后一个字段 > 4
NR % 2 == 0连记录
NR==10, NR==20记录 10 到 20
BEGIN{print ARGC}总参数
ORS=NR%5?",":"n"连接记录

例子

打印总和和平均值

awk -F: '{sum += $3}
     END { print sum, sum/NR }
' /etc/passwd

打印参数

awk 'BEGIN {
    for (i = 1; i < ARGC; i++)
        print ARGV[i] }' a b c

输出字段分隔符为逗号

awk 'BEGIN { FS=":";OFS=","}
    {print $1,$2,$3,$4}' /etc/passwd

打印该字符串匹配Tw的起始位置

awk 'BEGIN {
    if (match("One Two Three", "Tw"))
        print RSTART }'

打印该字符串匹配re的字符串长度

awk 'BEGIN {
    if (match("One Two Three", "re"))
        print RLENGTH }'

环境变量

ARGC数字或参数
ARGV参数数组
FNRFILEN的红棕色Records
OFMT数字格式
(默认为“%.6g”)
RSTART字符串中的位置
RLENGTH比赛时长
SUBSEP多维数组分隔符
(默认“34”)
ARGIND参数索引

仅限 GNU awk

ENVIRON环境变量
IGNORECASE忽略大小写
CONVFMT转换格式
ERRNO系统错误
FIELDWIDTHS固定宽度字段

定义变量

awk -v var1="Hello" -v var2="Wold" '
    END {print var1, var2}
' </dev/null

使用 shell 变量

awk -v varName="$PWD" '
    END {print varName}' </dev/null

awk 操作符

操作符

--
{print $1}第一个字段
$2 == "foo"等于
$2 != "foo"不等于
"foo" in array在数组中

正则表达式

--
/regex/线路匹配
!/regex/行不匹配
$1 ~ /regex/字段匹配
$1 !~ /regex/字段不匹配

更多条件

--
($2 <= 4 || $3 < 20)或者
($1 == 4 && $3 < 20)

运算符

算术运算

  • +
  • -
  • *
  • /
  • %
  • ++
  • --

速记作业

  • +=
  • -=
  • *=
  • /=
  • %=

比较运算符

  • ==
  • !=
  • <
  • >
  • <=
  • >=

例子

awk 'BEGIN {
    if ("foo" ~ "^fo+$")
        print "Fooey!";
}'

不匹配

awk 'BEGIN {
    if ("boo" !~ "^fo+$")
        print "Boo!";
}'

如果在数组中

awk 'BEGIN {
    assoc["foo"] = "bar";
    assoc["bar"] = "baz";
    if ("foo" in assoc)
        print "Fooey!";
}'

awk 函数

常用功能

FunctionDescription
index(s,t)字符串 s 中出现字符串 t 的位置,如果未找到则为 0
length(s)字符串 s 的长度(如果没有 arg,则为 $0)
rand0 到 1 之间的随机数
substr(s,index,len)返回从索引开始的 s 的 len-char 子串(从 1 开始计数)
srand为 rand 设置种子并返回之前的种子
int(x)将 x 截断为整数值
split(s,a,fs)将字符串 s 拆分为由 fs 拆分的数组 a,返回 a 的长度
match(s,r)字符串 s 中出现正则表达式 r 的位置,如果未找到则为 0
sub(r,t,s)将 t 替换为字符串 s 中第一次出现的正则表达式 r(如果未给出 s,则为 $0)
gsub(r,t,s)将 t 替换为字符串 s 中所有出现的正则表达式 r
system(cmd)执行cmd并返回退出状态
tolower(s)字符串 s 转小写
toupper(s)字符串 s 为大写
getline将 $0 设置为当前输入文件的下一条输入记录。

用户定义函数

awk '
    # Returns minimum number
    function find_min(num1, num2){
       if (num1 < num2)
       return num1
       return num2
    }
    # Returns maximum number
    function find_max(num1, num2){
       if (num1 > num2)
       return num1
       return num2
    }
    # Main function
    function main(num1, num2){
       result = find_min(num1, num2)
       print "Minimum =", result
      
       result = find_max(num1, num2)
       print "Maximum =", result
    }
    # Script execution starts here
    BEGIN {
       main(10, 60)
    }
'

awk 数组

带索引的数组

awk 'BEGIN {
    arr[0] = "foo";
    arr[1] = "bar";
    print(arr[0]); # => foo
    delete arr[0];
    print(arr[0]); # => ""
}'

带键的数组

awk 'BEGIN {
    assoc["foo"] = "bar";
    assoc["bar"] = "baz";
    print("baz" in assoc); # => 0
    print("foo" in assoc); # => 1
}'

拆分数组

awk 'BEGIN {
    split("foo:bar:baz", arr, ":");
    for (key in arr)
        print arr[key];
}'

带排序的数组

awk 'BEGIN {
    arr[0] = 3
    arr[1] = 2
    arr[2] = 4
    n = asort(arr)
    for (i = 1; i <= n ; i++)
        print(arr[i])
}'

多维数组

awk 'BEGIN {
    multidim[0,0] = "foo";
    multidim[0,1] = "bar";
    multidim[1,0] = "baz";
    multidim[1,1] = "boo";
}'

多维迭代

awk 'BEGIN {
    array[1,2]=3;
    array[2,3]=5;
    for (comb in array) {
        split(comb,sep,SUBSEP);
        print sep[1], sep[2], 
        array[sep[1],sep[2]]
    }
}'

awk 条件

if-else 语句

awk -v count=2 'BEGIN {
    if (count == 1)
        print "Yes";
    else
        print "Huh?";
}'

三元运算符

awk -v count=2 'BEGIN {
    print (count==1) ? "Yes" : "Huh?";
}'

存在

awk 'BEGIN {
    assoc["foo"] = "bar";
    assoc["bar"] = "baz";
    if ("foo" in assoc)
        print "Fooey!";
}'

不存在

awk 'BEGIN {
    assoc["foo"] = "bar";
    assoc["bar"] = "baz";
    if ("Huh" in assoc == 0 )
        print "Huh!";
}'

switch 语句

awk -F: '{
    switch (NR * 2 + 1) {
        case 3:
        case "11":
            print NR - 1
            break
        
        case /2[[:digit:]]+/:
            print NR
        
        default:
            print NR + 1
        
        case -1:
            print NR * -1
    }
}' /etc/passwd

Awk 循环

for...i

awk 'BEGIN {
    for (i = 0; i < 10; i++)
        print "i=" i;
}'

1 到 100 之间的 2 次幂

awk 'BEGIN {
    for (i = 1; i <= 100; i *= 2)
        print i
}'

for...in

awk 'BEGIN {
    assoc["key1"] = "val1"
    assoc["key2"] = "val2"
    for (key in assoc)
        print assoc[key];
}'

参数

awk 'BEGIN {
    for (argnum in ARGV)
        print ARGV[argnum];
}' a b c

例子

反向记录

awk -F: '{ x[NR] = $0 }
    END {
        for (i = NR; i > 0; i--)
        print x[i]
    }
' /etc/passwd

反向字段

awk -F: '{
    for (i = NF; i > 0; i--)
        printf("%s ",$i);
    print ""
}' /etc/passwd

按记录求和

awk -F: '{
    s=0;
    for (i = 1; i <= NF; i++)
        s += $i;
    print s
}' /etc/passwd

总和整个文件

awk -F: '
    {for (i = 1; i <= NF; i++)
        s += $i;
    };
    END{print s}
' /etc/passwd

while 语句

awk 'BEGIN {
    while (a < 10) {
        print "- " " concatenation: " a
        a++;
    }
}'

do...while 语句

awk '{
    i = 1
    do {
        print $0
        i++
    } while (i <= 5)
}' /etc/passwd

break

awk 'BEGIN {
    break_num = 5
    for (i = 0; i < 10; i++) {
        print i
        if (i == break_num)
            break
    }
}'

continue

awk 'BEGIN {
    for (x = 0; x <= 10; x++) {
        if (x == 5 || x == 6)
            continue
        printf "%d ", x
    }
    print ""
}'

Awk 格式化打印

用法

右对齐

awk 'BEGIN{printf "|%10s|n", "hello"}'

|     hello|

左对齐

awk 'BEGIN{printf "|%-10s|n", "hello"}'

|hello     |

常用说明符

CharacterDescription
cASCII 字符
d十进制整数
eE,f浮点格式
o无符号八进制值
s细绳
%文字百分比

空间

awk -F: '{
    printf "%-10s %sn", $1, $(NF-1)
}' /etc/passwd | head -n 3

输出

root       /root
bin        /bin
daemon     /sbin

标题

awk -F: 'BEGIN {
    printf "%-10s %sn", "User", "Home"
    printf "%-10s %sn", "----","----"}
    { printf "%-10s %sn", $1, $(NF-1) }
' /etc/passwd | head -n 5

输出

User       Home
----       ----
root       /root
bin        /bin
daemon     /sbin

其他

正则表达式元字符

  • ^
  • $
  • .
  • [
  • ]
  • |
  • (
  • )
  • *
  • +
  • ?

转义序列

b退格
f换页
n换行(换行)
r回车
t水平标签
v垂直标签

运行脚本

$ cat demo.awk
#!/usr/bin/awk -f
BEGIN { x = 23 }
      { x += 2 }
END   { print x }
$ awk -f demo.awk /etc/passwd
69

另见