網(wǎng)上很多關(guān)于Linux Shell這方面的教程質(zhì)量參差不齊,所以在這里收獲不小后,決定寫篇博客,方便更多的人學(xué)習(xí)。
本文題集基于小練習(xí),數(shù)據(jù)請自行下載。
這些題的答案都是我自己寫的,感覺很多都只是實(shí)現(xiàn)了功能但是并不高效,希望大家能在評論區(qū)留下更好的答案,一起交流。現(xiàn)在我在很多地方都能用上這些強(qiáng)大的命令,所以想為這個題集做點(diǎn)貢獻(xiàn),方便大家。
一、Linux Shell入門
推薦閱讀
Quiz 1 一個接受命令行參數(shù)的shell腳本
任務(wù) 編寫一個shell腳本1.sh,這個腳本接受一個命令行參數(shù),并把這個參數(shù)打印兩次到標(biāo)準(zhǔn)輸出。如果輸入沒有參數(shù)輸入或者有多于一個參數(shù)輸入,輸出"error"。
樣例 1.
./1.sh hello
hellohello
樣例 2.
./1.sh
error
運(yùn)行命令
sh 1.sh [ARGUMENT]
Quiz1 我的代碼如下
#!/bin/bash
if [ $# -eq 1 ]
then echo "$1$1"
else
echo "error"
fi
$1: 表示輸入的參數(shù)
$#: 表示輸入的參數(shù)數(shù)目
Quiz 2 生成時間相關(guān)文件夾
任務(wù) 編寫一個shell腳本2.sh,無論腳本在任何位置用絕對路徑執(zhí)行都能完成這樣的任務(wù),在腳本2.sh所在目錄新建一個空文件tmp_YYYYMMDD YYYYMMDD為當(dāng)前日期
運(yùn)行命令
命令:
sh src/2.sh; ls src
輸出:
2.sh tmp_20130329
Quiz2 我的代碼如下
#!/bin/bash
mkdir 'tem_'`date '+%Y%m%d'`
二、學(xué)習(xí)grep
推薦閱讀
題目
你需要用grep腳本(或者用grep和其他shell命令配合)實(shí)現(xiàn)如下一些功能
Quiz 1
任務(wù) 請完成腳本1.sh,統(tǒng)計文件中的空行個數(shù)并輸出
數(shù)據(jù) 1.dat
測試命令
sh 1.sh
Quiz1 我的代碼如下
#!/bin/bash
echo `grep '^$' 1.dat | wc -l`
^$表示開頭即結(jié)尾-也就是空行,再用wc統(tǒng)計下行數(shù)即可。
Quiz 2
任務(wù) 請完成腳本2.sh,統(tǒng)計文件中不包含".txt"的行的行數(shù)并輸出
數(shù)據(jù) 2.dat
測試命令
sh 2.sh
Quiz2 我的代碼如下
#!/bin/bash
echo `grep -v '.txt' 2.dat`
先找到含.txt的行,再用-v參數(shù),含義為--invert-match, 即取逆。
Quiz 3
任務(wù) 請完成腳本3.sh,求兩個文件的差集(3a.txt-3b.txt)并排序輸出到標(biāo)準(zhǔn)io中
測試命令
sh 3.sh
Quiz3 我的代碼如下
#!/bin/bash
echo `grep -f 3b.dat 3a.dat -v`
-f [arg]:從文件[arg]中取patterns。
-v參數(shù):取逆。
所以上面命令的含義是:根據(jù)3b.dat的所有行建立pattern,從3a.dat中找到符合此pattern的行(此時即為3b.dat∩3a.dat),再取3a.dat的逆。
故流程為:
- 第一步:返回3b.dat∩3a.dat
- 第二步:返回3a.dat - (3b.dat∩3a.dat) = 3a.dat - 3b.dat
Quiz 4
任務(wù) 在log文件中,有表示各輪迭代模型性能的報告(如下所示),
Total: P=0.97198463(7841/8067) R=0.97914585(7841/8008) F=0.97555210
請將他們提取出來,并以如下格式輸出。
P=0.97 R=0.98 F=0.98
數(shù)據(jù) 4.dat
測試命令
sh 4.sh
Quiz4 我的代碼如下
#!/bin/bash
grep 'Total:' 4.dat | sed 's/[a-zA-Z :*=]//g' | awk '{printf("P=%.2f R=%.2f F=%.2f \n", $1, $2, $3)}'
流程如下:
- 第一步:用grep取出含
Total:的行。 - 第二步:用sed將此行中的
空格 : * =及字母全部刪除。 - 第三步:用awk將數(shù)據(jù)按格式輸出。
三、學(xué)習(xí)Awk
推薦閱讀
題目
Quiz1
輸出一個文件所有的偶數(shù)行,數(shù)據(jù)1.dat。
Quiz1 我的代碼如下
#!/bin/bash
awk '!(NR%2)' 1.dat
NR表示:操作的當(dāng)前行數(shù)。
如果操作的行數(shù)不是奇數(shù),則輸出。
Quiz2
對于一個保存單詞 頻率的文件,要同時計算它的累積頻率,并將它填在第三列,數(shù)據(jù)2.dat。
舉例如下,輸入文件是
the 100
i 50
is 45
...
輸出文件是
the 100 100
i 50 150
is 45 195
...
Quiz2 我的代碼如下
#!/bin/bash
awk '{count=count+$2;printf("%s %d\n", $0, count)}' 2.dat
利用count暫存第二列數(shù)據(jù),然后在該行第三列打印出即可。
Quiz3
讀入一個包含詞性的文件,從中提取出原始句子。
輸入文件格式:
石家莊_ns 空氣_n 污染_vn 排_v 第一_m
潘石屹_ns 遭遇_v 被_p 代言_n
...
輸出文件:
石家莊空氣污染排第一
潘石屹遭遇被代言
...
Quiz3 我的代碼如下
#!/bin/bash
sed 's/_[a-zA-Z ]*//g' 3.dat
將_和后面的詞性及空格去掉即可。
四、學(xué)習(xí)sed
推薦閱讀
題目
請使用sed完成下列任務(wù)。當(dāng)然,你也可以使用之前的shell命令(比如awk、grep)與sed配合。
Quize 1
任務(wù) 去掉文件中的空行
數(shù)據(jù)1.dat
Quiz1 我的代碼如下
#!/bin/bash
sed 's/ //g' 1.dat
Quiz 2
任務(wù)某個文件包含三列,第三列是文本,但是文本被'擴(kuò)了起來,請用提取出這一列并去掉開頭和結(jié)尾的'符號。
數(shù)據(jù)2.dat
Quiz2 我的代碼如下
#!/bin/bash
cut -d " " -f 7- 2.dat | sed "s/^'//g;s/'$//g"
將第三列取出,再取出前后的'符號即可。
五、學(xué)習(xí)Uniq和Sort
Quiz 1
Find out the most frequency 100 queries from the query log
有用戶日志文件,每行記錄了一個用戶查詢串,長度為1-255字節(jié),共1千萬行,請排出查詢最多的前100條。數(shù)據(jù)query_log.txt。
提示
- 使用uniq -c 可以統(tǒng)計詞頻
- 使用sort -k <column>可以指定對輸入按照第<column>列進(jìn)行排序
- 使用sort -n 可以指定采用數(shù)值方法進(jìn)行排序
- 使用sort -r 可以指定逆序排序
- 使用sed將空格替換為\n
Quiz1 我的代碼如下
#!/bin/bash
sort query_log.txt | uniq -c | sort -r | head -100
通過uniq統(tǒng)計行數(shù),再用sort逆序排序,再用head輸出前100行即可。
這里有個坑點(diǎn)是數(shù)據(jù)要先sort一下不然會出現(xiàn)重復(fù)詞無法集中統(tǒng)計的問題,詳細(xì)可以見uniq的manual描述:

直白的翻譯是:
輸入中不相鄰的重復(fù)行不會被發(fā)現(xiàn),所以你可能需要先對文件排序。