Linux常用命令是每个开发人员必须熟练掌握的,也是面试过程中经常被问到的知识点。下面给大家分享 Linux常用命令面试题 系列文章,持续更新,敬请关注。
cat file | head -n 5000 | tail -n +2000 # 显示2000行到5000行
tail -n +2000 表示的是从2000行开始显示;
tail -n 2000 表示的是显示文件最后2000行,差别很大,注意灵活使用。
务必注意:head与tail的前后顺序。 如果将tail 放前面,如下命令: cat file | tail -n +2000 | head -n 5000 表示的是 : 从第2000行开始,共显示5000行,也就是2000~6999行!
find ./ -name "*.log" -type f -mtime +90 -size +10G -maxdepth 1 -print -exec rm {} \;
文件a 1 2 1 3 4 2 文件b 1 4 2 5 6 1
方法1 : 使用comm实现,配合sort和uniq命令
# 交集
comm -12 <(sort a|uniq) <(sort b|uniq)
# 差集:a-b
comm -23 <(sort a|uniq) <(sort b|uniq)
# 差集:b-a
comm -13 <(sort a|uniq) <(sort b|uniq)
方法2:使用grep实现,结合 参数-vFf
# 交集
grep -Ff a b|sort|uniq
# 差集:a-b
grep -vFf b a
# 差集:b-a
grep -vFf a b
1. comm命令
comm缺点:待比较文件需要先(sort|uniq)预处理
2. grep命令
sed -i '/^$/d' A B
去除。grep -vFf b a
的结果是差集b-a。grep缺点:需要先对每个文件进行空行删除处理
文件内容: a a a b b b c c c d d d 输出格式: a:3 b:1 b:2 c:3 d:3
cat file|awk -F' ' '{delete a; for(i=1;i<=NF;i++) a[$i]++; for(i in a) printf i":"a[i]"\t"; printf "\n"}'
该命令的主体是一个awk语句:awk -F' ' '{}'
, 其中,-F指定每行的分隔符, '{}'
是每行要执行的命令。
需要提醒的是awk、grep、sed
这些文本处理命令,都是按行遍历处理的。
首先我们提取awk
核心语句'{}'
中的内容:
{delete a; for(i=1;i<=NF;i++) a[$i]++; for(i in a) printf i":"a[i]"\t"; printf "\n"}
根据分号提示,我们可以将其分为四个部分:
1. delete a;
先不管这个,看下一个
2. 遍历每行每个列元素,把每个列元素出现的次数记录下来。
for(i=1;i<=NF;i++) a[$i]++;
其中,NF
表示每行的总列数,$i
是该列具体内。
a[$i]++
是建立一个数组(字典),其中,key为$i
, value为$i
的出现次数。
通过for
循环,遍历每行的每个列,将各个列的出现次数进行了汇总求和。
3. 每行统计完之后,打印统计数组a
for(i in a) printf i":"a[i]"\t";
通过for
循环,逐个打印该行统计字典a
的每个item
。
printf
是格式化输出,打印完不回车。
4. 该行统计结束后,最后要打印一个回车符,然后继续下一行的统计。
printf "\n"
那么问题来了,此时是不是应该将数组a
中的元素清除??想一想,如果不清楚a
的话,遍历后面行的时候,每个item
会在前面统计次数的结果上继续累加!
也就是我们上面跳过的第1步 : deleta a;
它的作用是:
每行开始统计前,都要清空上一行的统计数组a的内容,新行的统计结果会放到空的a
中。
文件内容: advertiserId:0001 displayNum:100 orderNum:2 advertiserId:0001 displayNum:300 orderNum:4 advertiserId:0003 displayNum:500 orderNum:12 advertiserId:0004 displayNum:200 orderNum:8 输出格式: 0001 400 6 0003 500 12 0004 200 8
cat file|awk '{match($0,/advertiserId:([0-9]*) displayNum:([0-9]*) orderNum:(.*)/,a);print a[1],a[2],a[3]}'|awk '{a[$1][0]+=$2;a[$1][1]+=$3} END{for(i in a) print i,a[i][0],a[i][1]}'
该命令主要由两个awk
通过管道连接组成,对每个awk
分别讲解:
(1)第一个awk
:将所需要的字段匹配打印出来
通过执行第一个awk
语句,可以输出下列格式:
0001 100 2 0001 300 4 0003 500 12 0004 200 8
awk '{match($0,/advertiserId:([0-9]*) displayNum:([0-9]*) orderNum:(.*)/,a);print a[1],a[2],a[3]}'
该部分的主体是两个函数:match
匹配函数和print
函数。
(1)match
函数部分
格式:match(string,regex,array)
参数介绍:
string是要匹配的字符串
regex是正则表达式
array是匹配出内容的存储数组
因此,回到我们的match
匹配例子。
match($0,/advertiserId:([0-9]*) displayNum:([0-9]*) orderNum:(.*)/,a);
第1个参数我们使用$0
,也就是一整行。
第2个参数是一个匹配表达式:
/advertiserId:([0-9]*) displayNum:([0-9]*) orderNum:(.*)/
表达式需要两个“/”作为start和end标志,后续需要用到的item
需要用()括起来。
第3个参数是一个数组名称,我们用a
表示,这样数组a
就可以将前面的三个()里面的item
存下来了。
(2)print部分
print a[1],a[2],a[3];
这个语句的作用就是:将每行统计数组a中的各个统计项打印出来。
总结:第一个awk
的作用是将我们需要的字段匹配出来,并统计好,打印出来。
(2)第二个awk
:根据advertiserId汇总各行
首先,重申一下第一个awk
执行完之后的输出结果:
0001 100 2 0001 300 4 0003 500 12 0004 200 8
第二个awk
的内容是:
awk '{a[$1][0]+=$2;a[$1][1]+=$3} END{for(i in a) print i,a[i][0],a[i][1]}'
主要包括两个部分: 每行执行语句和END{}结束语句。
(1)每行执行语句
{a[$1][0]+=$2;a[$1][1]+=$3}
这里,可以把 a
理解为一个python字典,key是广告商ID,也就是第一个awk
执行后输出结果的$1
。
value是一个数组,存储两个数据:
$2
$3
因此,通过执行上面的语句,可以将每个广告商的广告展示数和成单数进行汇总。
注意: 本题和第一题不同的是,不用再执行每一行时,清空a中的元素,因为本题是对所有行进行广告商维度的汇总统计,而不是统计完每行都要汇总一下。
(2) END{}结束语句
END{}语句的执行时机是:awk
对所有的行遍历汇总完之后,汇总结果保留在字典a
中。
通过执行下面语句,可以将汇总字典a中的各项内容清晰打印出来:
END{for(i in a) print i,a[i][0],a[i][1]}
其中,i
是广告商ID,a[i][0]
是该广告商的广告展示数,a[i][1]
是成单数。