这是一份 GNU awk 的单页快速参考备忘单,涵盖了常用的 awk 表达式和命令。
$ awk -F: '{print $1, $NF}' /etc/passwd
- | - |
---|---|
-F: |
使用冒号作为分隔符 |
{...} |
Awk 程序 |
print |
打印当前记录 |
$1 |
第一个字段 |
$NF |
最后一个字段 |
/etc/passwd |
输入数据文件 |
BEGIN {<初始化>}
<模式 1> {<程序动作>}
<模式 2> {<程序动作>}
...
END {< 最终动作 >}
awk '
BEGIN { print "\n>>>开始" }
!/(login|shutdown)/ { print NR, $0 }
END { print "<<<结束\n" }
' /etc/passwd
$1 $2/$(NF-1) $3/$NF
▼ ▼ ▼
┌──────┬──────────────────┬───────┐
$0/NR ▶ │ ID │ 网站 │ URI │
├──────┼──────────────────┼───────┤
$0/NR ▶ │ 1 │ r3f.cn │ awk │
├──────┼──────────────────┼───────┤
$0/NR ▶ │ 2 │ google.com │ 25 │
└──────┴──────────────────┴───────┘
# 第一个和最后一个字段
awk -F: '{print $1,$NF}' /etc/passwd
# 带行号
awk -F: '{print NR, $0}' /etc/passwd
# 倒数第二个字段
awk -F: '{print $(NF-1)}' /etc/passwd
# 自定义字符串
awk -F: '{print $1 "=" $6}' /etc/passwd
参见:Awk 变量
awk 'BEGIN {print "hello world"}' # 打印 "hello world"
awk -F: '{print $1}' /etc/passwd # -F: 指定字段分隔符
# /模式/ 仅对匹配的模式执行操作
awk -F: '/root/ {print $1}' /etc/passwd
# BEGIN 块在开始时执行一次
awk -F: 'BEGIN { print "uid"} { print $1 }' /etc/passwd
# END 块在结束时执行一次
awk -F: '{print $1} END { print "-完成-"}' /etc/passwd
- | - |
---|---|
$0 |
整行 |
$1, $2...$NF |
第一个、第二个…最后一个字段 |
NR |
记录N umber of R ecords |
NF |
字段N umber of F ields |
OFS |
输出O utput F ield S eparator (默认为 " ") |
FS |
输入F ield S eparator (默认为 " ") |
ORS |
输出O utput R ecord S eparator (默认为 "\n") |
RS |
输入R ecord S eparator (默认为 "\n") |
FILENAME |
文件名 |
- | - |
---|---|
$1 == "root" |
第一个字段等于 root |
{print $(NF-1)} |
倒数第二个字段 |
NR!=1{print $0} |
从第二条记录开始 |
NR > 3 |
从第四条记录开始 |
NR == 1 |
第一条记录 |
END{print NR} |
总记录数 |
BEGIN{print OFMT} |
输出格式 |
{print NR, $0} |
行号 |
{print NR " " $0} |
行号 (制表符) |
{$1 = NR; print} |
用行号替换第一个字段 |
$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
匹配位置
awk 'BEGIN {
if (match("One Two Three", "Tw"))
print RSTART }'
匹配长度
awk 'BEGIN {
if (match("One Two Three", "re"))
print RLENGTH }'
- | - |
---|---|
ARGC |
参数数量 |
ARGV |
参数数组 |
FNR |
文件F ile N umber of R ecords |
OFMT |
数字格式 (默认为 "%.6g") |
RSTART |
字符串中的位置 |
RLENGTH |
匹配长度 |
SUBSEP |
多维数组分隔符 (默认为 "\034") |
ARGIND |
参数索引 |
- | - |
---|---|
ENVIRON |
环境变量 |
IGNORECASE |
忽略大小写 |
CONVFMT |
转换格式 |
ERRNO |
系统错误 |
FIELDWIDTHS |
固定宽度字段 |
函数 | 描述 |
---|---|
index(s,t) |
字符串 t 在字符串 s 中出现的位置,如果未找到则为 0 |
length(s) |
字符串 s 的长度 (如果没有参数则为 $0) |
rand |
0 到 1 之间的随机数 |
substr(s,index,len) |
返回 s 中从 index (从 1 开始计数) 开始的 len 个字符的子字符串 |
srand |
设置 rand 的种子并返回先前的种子 |
int(x) |
将 x 截断为整数值 |
split(s,a,fs) |
将字符串 s 按 fs 分割到数组 a 中,返回 a 的长度 |
match(s,r) |
正则表达式 r 在字符串 s 中出现的位置,如果未找到则为 0 |
sub(r,t,s) |
在字符串 s 中 (如果未给出 s 则为 $0) 用 t 替换第一次出现的正则表达式 r |
gsub(r,t,s) |
在字符串 s 中用 t 替换所有出现的正则表达式 r |
system(cmd) |
执行 cmd 并返回退出状态 |
tolower(s) |
字符串 s 转为小写 |
toupper(s) |
字符串 s 转为大写 |
getline |
将 $0 设置为当前输入文件中的下一个输入记录。 |
awk '
# 返回最小值
function find_min(num1, num2){
if (num1 < num2)
return num1
return num2
}
# 返回最大值
function find_max(num1, num2){
if (num1 > num2)
return num1
return num2
}
# 主函数
function main(num1, num2){
result = find_min(num1, num2)
print "Minimum =", result
result = find_max(num1, num2)
print "Maximum =", result
}
# 脚本从这里开始执行
BEGIN {
main(10, 60)
}
'
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 -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!";
}'
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 'BEGIN {
for (i = 0; i < 10; i++)
print "i=" i;
}'
awk 'BEGIN {
for (i = 1; i <= 100; i *= 2)
print i
}'
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
awk 'BEGIN {
while (a < 10) {
print "- " " concatenation: " a
a++;
}
}'
awk '{
i = 1
do {
print $0
i++
} while (i <= 5)
}' /etc/passwd
awk 'BEGIN {
break_num = 5
for (i = 0; i < 10; i++) {
print i
if (i == break_num)
break
}
}'
awk 'BEGIN {
for (x = 0; x <= 10; x++) {
if (x == 5 || x == 6)
continue
printf "%d ", x
}
print ""
}'
字符 | 描述 |
---|---|
c |
ASCII 字符 |
d |
十进制整数 |
e , E , f |
浮点数格式 |
o |
无符号八进制值 |
s |
字符串 |
% |
字面量 % |
awk -F: '{
printf "%-10s %s\n", $1, $(NF-1)
}' /etc/passwd | head -n 3
输出
root /root
bin /bin
daemon /sbin
awk -F: 'BEGIN {
printf "%-10s %s\n", "User", "Home"
printf "%-10s %s\n", "----","----"}
{ printf "%-10s %s\n", $1, $(NF-1) }
' /etc/passwd | head -n 5
输出
User Home
---- ----
root /root
bin /bin
daemon /sbin