Linux常用指令是每個開發人員必須熟練掌握的,也是面試過程中經常被問到的知識點。下面給大家分享 Linux常用指令面試題 系列文章,持續更新,敬請關注。
1. 顯示一個檔案的第2000-5000行。
指令:
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行!
2. 将目前目錄下以".log"結尾且修改時間大于90天的5G以上的大檔案删除。
指令:
find ./ -name "*.log" -type f -mtime +90 -size +10G -maxdepth 1 -print -exec rm {} \;
複制
解析:
- -name "*.log" : 按名稱查找,如果忽略大小寫,則用-iname,注意引号别丢;
- -type f :檔案類型限定為檔案,目錄是d
- -mtime +90 :修改時間大于90天。-n指n天以内,+n指n天以前
- -size +10G :檔案size過濾
- -maxdepth 1 :限制查找最大深度,目前目錄是1
- -print :将找到的檔案以相對路徑的形式打出來
- -exec rm {} \; 找到的檔案将執行删除指令,最後是"空格"+{}+"分号;"都不能省。
- 補充:
- 如果是删除檔案,用rm -rf ;
- 如果想要删除前确認,将" -exec rm {} \;"替換成"-ok rm {} \;"
3. 有兩個檔案a和b,如下所示,請統計兩個檔案的交集、差集。
檔案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比較的兩個檔案A和B,必須是排序和唯一(sorted and unique)的,所有要用sort|uniq進行預處理。
- comm預設輸出三列,第一列為是差集A-B,第二列是差集B-A,第三列為A交B。
- comm指令參數:
- -m m可以是1,2,3,表示的是不顯示第m列,隻顯示剩餘的兩列。
- -mn 同理,不顯示第m列和第n列,隻顯示剩下的一列。
- "<"表示輸入重定向,即輸入不從鍵盤讀入,而是從檔案輸入或其它。從指令輸入時括号不可省略。
comm缺點:待比較檔案需要先(sort|uniq)預處理
2. grep指令
- grep比較的兩個檔案不需要排序和去重,但是不能有空行,否則不能比較。
- 空行可以用
去除。sed -i '/^$/d' A B
- -Ff參數是求交集,但是結果沒有排序和去重,需要用sort|uniq處理下
-
-vFf是求差集,這裡需要注意檔案的先後順序,可以這樣記憶:
哪個檔案在後,結果顯示的是隻包含在該檔案中的内容
比如:
的結果是差集b-a。grep -vFf b a
grep缺點:需要先對每個檔案進行空行删除處理
4. 有下面一個檔案,請統計每行中每個元素出現的次數并按指定格式輸出:
檔案内容:
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
中。
5. 有一個檔案如下,請統計每個廣告商的展示廣告總數和成單總數。
檔案内容:
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]
是成單數。