awk 命令之常见问题

保留最新的9个文件
ls -t /tmp/ | awk '{if(NR>9){print $0}}' | while read line; do rm -f /tmp/$line; done

#下面的指令在文件太多的时候不能成功执行
ls -t /tmp/ | awk '{if(NR>9){print $0}}' | xargs rm -f

将/home/test 目录下大于10K的文件转移到/tmp目录下
#!/bin/sh
cd /home/test
for i in `ls -l |awk '{if($5>10240) {print $9}}'`
do
mv $i /tmp
done

 {print $0}           打印所有输出行
NR==8 { print $0} 打印输入文件第八行
{if(NR==8){print $0}}
awk -F: '{print $1}' 打印文件所有行的第一个字段
awk 'END{print NR}' 打印输入行总数
awk -F: '{print $0,NF}' 打印每行字段数
awk -F: 'END{print $NF}' 打印最后一行的最后一个字段的值
awk -F: 'NF>=4{print $0}'打印字段多余4行的行
awk -F: 'BEGIN(num=0) {num=num+NF}END{print num}' 打印文件所有字段的总数
awk -F: '$3>=30 && $4 <=40{print $1}' 打印uid在30~40范围的用户名
{i=NF while(i>0){printf ("%s:",$i);i=i-1}printf("\n")}倒序排列文件的所有字段
print直接换行printf需要\n此换行,%s输出字符串
awk -F: 'NR>=5&&NR<=56{print $0}' 打印5到56行
awk 'BEGIN{print "Document"}{print $0}'在文件顶部加上标题“Document”
awk 'NF%2==0{print $0,NF}' 隔行删除偶数行
awk 'NF%2==1{print $0,NF}' 隔行删除奇数行
BEGIN{FS="[^a-zA-Z]"}{i=1,j=0,while(NF-i!=0){if($i){j=j+1}if(j==1){printf("%s "$i)}i=i+1}printf("\n")} 非字母的分段 i定义的字段,j用来判断是否为单词 每行抽出第一个单词
BEGIN{FS="[^a-zA-Z]"}{i=1,j=0,while(NF-i!=0){if($i){j=j+1}if(j==1&&j==3){printf("%s "$i)}i=i+1}printf("\n")} 打印每行的第一个单词和第三个单词
BEGIN{FS=":",num=0}{if(NF>5){num=num+NF}}END{print num} 打印字段数大于5个的行总数

1. awk ‘{code}1’ 中的“1”是干什么的?

一个完整的awk语句为:Awk ‘[patten]{action}……’, 其中pattern缺省为1,action缺省为{print}。

那么awk ‘1’完整的写法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的写法也是awk ‘1{print}’。

2. NR和FNR的区别是啥?

NR: 当前行记录数。

FNR: 当前文件的行记录数。

当awk处理的文件数超过1时,NR和FNR才会有区别。例如:
cat file
a
b
c
d
e
f

awk '{print "NR = " NR " FNR = " FNR, $0}' file
NR = 1 FNR = 1 a
NR = 2 FNR = 2 b
NR = 3 FNR = 3 c
NR = 4 FNR = 4 d
NR = 5 FNR = 5 e
NR = 6 FNR = 6 f

awk '{print "NR = " NR " FNR = " FNR, $0}' file file
NR = 1 FNR = 1 a
NR = 2 FNR = 2 b
NR = 3 FNR = 3 c
NR = 4 FNR = 4 d
NR = 5 FNR = 5 e
NR = 6 FNR = 6 f
NR = 7 FNR = 1 a
NR = 8 FNR = 2 b
NR = 9 FNR = 3 c
NR = 10 FNR = 4 d
NR = 11 FNR = 5 e
NR = 12 FNR = 6 f

3. Awk怎么引入变量?

有两种方法:

<1>: awk -v var=$VAR '{code}'
<2>: awk '{CODE}'$VAR'{CODE}'
例如:
VAR=XXX

awk -v var=$VAR 'BEGIN{print var}'
XXX

awk 'BEGIN{print "'$VAR'"}'
XXX

推荐使用第一种方法,这样可以避免一些不必要的烦恼。
4. 为什么OFS不起作用?

先看一个例子:
echo 'aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd' |awk -v OFS="|" '{print $0}'
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd

上面的例子中OFS为什么没有生效呢,原因是OFS指的是输出字段分隔符,所以必须对字段进行操作时OFS才会起作用,正确的方法应该是:
echo 'aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd
aaa bbb ccc ddd' |awk -v OFS="|" '{$1=$1;print $0}'
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
正如Tim大师所讲的,$1=$1这个action,是我们对awk撒的谎,目的就是为了使得OFS生效,除此之外,NF+=0也是常用的方法。

5. print,printf 和sprintf?

print:默认有个换行\n,为一般的打印

printf:可以定义打印格式,能打印各种格式,但默认没有换行。

sprintf:可以完成和printf相同的功能,不同的是sprintf只能输出值,并不能完成打印的功能。
awk 'BEGIN{var=123; print "var = " var}'
var = 123

awk 'BEGIN{var=123;printf "%s %5f\n", "var =",var}'
var = 123.000000

awk 'BEGIN{var=123;sprintf ("%s %5f\n", "var =",var)}'


awk ‘BEGIN{var1=123;var2=sprintf ("%5f",var1); print "var2 =" var2}’
var2 = 123.000000

6. 如何打印单双引号?
awk 'BEGIN {print "single quote --> \047";print "double quote --> \042" }'

7. awk 语句中多个{}是怎么执行的?
cat file
1
2
3
4
5

awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 这个语句中包含三个action
@@ 11 # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
@@ 22 # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
|| 3 @@ 33 # 判断$1==3?是,执行{print “|| “$0}; 执行 action {printf " @@ "$0};执行 action {print $0}
@@ 44 # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}
@@ 55 # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

这样可以清楚的看出,awk是一行一行读取文本,然后按照代码的前后顺序执行。但如果action中包含next或exit时,有所不同:
awk '$1==3{printf "|| "$0;next}{printf "@@ "$0}{print $0}' file
@@ 11
@@ 22
|| 3@@ 44
@@ 55

awk '$1==3{printf "|| "$0;exit}{printf "@@ "$0}{print $0}' file
@@ 11
@@ 22
|| 3

你可能感兴趣的:(awk 命令之常见问题)