實踐中,你用過哪些由簡單命令組裝起來的複雜命令行?
曾經在"The Unix Programming Environment"這本書里,學到這樣一個命令(這裡沒有去翻原書,不保證一模一樣,但基本差不多):
cat english.txt | sed s/[^a-zA-Z]/
/g | tr [A-Z] [a-z] | sort | uniq -c | sort -k 1 -n -r | awk NF==2 | head -20這個命令的功能是輸出文本文件english.txt中出現次數最高的前20個單詞,除了沒有考慮詞的屈折變化,功能基本算是完善。
早年,我開始讀自然語言處理方向研究生時,曾經用過這樣的管道程序:
cat chinese.txt | sentence | word_segmentation | pos_tagging | parsing | EBMT
這個命令是對輸入中文chinese.txt,依次進行斷句、分詞、詞性標註、句法分析,最後做基於實例的機器翻譯(當年還沒有什麼深度學習,這些步驟沒有融合)。
此外,我在下面這個回答中,
知乎 - 知乎所用的命令為:
cat *.h *.cpp | fgrep -o -w -f all.reserved-words-c++.txt | sort | uniq -c | sort -k1 -n -r
問題:你在實際工作中,還使用過什麼樣的由很簡單命令組裝起來的複雜命令行?組裝機制不限於管道,但最好不是單一AWK程序放到一行的那種。
之前查內存泄漏,在alloc和free的地方列印日誌,用ptr關聯一對申請釋放,並打出size和backtrace,用一段grep和awk統計topN申請未釋放的alloc位置
egrep "#ALLOC|#FREE" | awk {if ($6 == "#ALLOC") {a[$7]=$0} else if ($6 == "#FREE") {delete a[$7]}} END{for (k in a) {print a[k]}} | awk {for (i=8; i&<=NF; i++) {printf("%s ", $i)} printf(" ")} | sort | uniq -c | awk {printf("%d %s ", $1*$2, $0)} | sort -n -k 1
還有一個是用樹莓派接上公司辦公網,通過兩層反向ssh代理來越過relay機器,但是pi重啟後我不知道它的新ip,所以搞了個crontab,讓pi把ifconfig寫到s3。所以越過relay的登錄腳本就是先curl s3,拿到地址後再兩跳去開發機。。。這麼好的問題,怎麼沒什麼人來回答呢。我自己先拋個磚,有好的回答後,我還會持續更新此答案。
研究期貨市場時,有時我需要知道某個合約自上市以來每天的平均價格,我把當前研究的所有價格數據放到everythinginone.txt中,具體格式實例如下:
2004-12-16 ISF2005.csv 0 0 0 524.0
2004-12-17 ISF2005.csv 0 0 0 524.0
2004-12-20 ISF2005.csv 0 0 0 524.0
2004-12-21 ISF2005.csv 0 0 0 524.0
2004-12-22 ISF2005.csv 0 0 0 524.0
2004-12-23 ISF2005.csv 0 0 0 524.0
2004-12-27 ISF2005.csv 0 0 0 524.0
2004-12-28 ISF2005.csv 0 0 0 524.0
2004-12-29 ISF2005.csv 0 0 0 524.0
2004-12-30 ISF2005.csv 0 0 0 524.0
這樣,比如我想得到ISF2010合約的平均價格數據,可以用這個命令:
cat everytinginone.txt | grep ISF2010 | awk {n++; s+=$6; print NR, s/n} &> avg
得到的avg文件大概長這樣:
1 1461.75
2 1436.75
3 1426.75
4 1411.75
5 1392.75
6 1379.25
7 1368.18
8 1358.12
9 1351.42
10 1341.05
然後,可以在上述命令的尾巴上加點東西,把圖形畫出來:
cat everytinginone.txt | grep ISF2010 | awk {n++; s+=$6; print NR, s/n} &> avg; gnuplot -p -e "plot avg with lines"
就得到這樣的圖:
這樣的命令並不很長,但確實是實踐中所用,避免了寫很多用完就扔的小程序。
兩個實用但不算太複雜的sample (Mac):
1. 統一更改某文件夾裹所有txt檔案: sed -i -e s/toDel/toAdd/g $(find . -name "*.txt")
2. Ping 所有host table裹的ip: grep -v "#" /etc/hosts | grep -oE "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}" | sort | uniq | while read pinip ; do ping -c 1 "$pinip" &> /dev/null ;if [ $? -eq 0 ]; then echo "node $pinip is up" ; else echo "node $pinip is down"; fi ; done
這個問題好莫名其妙... 我可以寫幾個內部邏輯超級複雜的幾個小程序,但是調用極其容易(參數簡單)。
標準輸出當做後續參數用管道串起來執行... 複雜程度可以無上限。。。
剛剛寫的
find . -type f -exec sh -c "iconv -f GBK -t UTF-8 {} &> {}"講真,越來越不願意使用那麼多命令,再用*管道*串起來。
有些命令是常見的,有些是自己寫的或者少見,再加上各式各樣的參數,可讀性真的好么,時間久了恐怕自己都忘了。
不是太圖省事的,還真不如你提的就用 one-line awk。至少語法是一致的,懂awk的人一定懂。
推薦閱讀:
※Windows 和 Unix 下的命令操作有什麼迷人之處?
※PowerShell 與 Bash 相比,哪個更好?
※如何善加利用 Mac 下的 Terminal ?
※DOS的常用命令都有哪些?如何應用?
※為什麼命令行界面(CLI)並未隨著命令行操作系統(如 DOS)的淘汰而消亡?