天天看點

Linux常用指令面試題(1)

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是求差集,這裡需要注意檔案的先後順序,可以這樣記憶:

    哪個檔案在後,結果顯示的是隻包含在該檔案中的内容

    比如:

    grep -vFf b a

    的結果是差集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]

是成單數。