工作8年,前6年基本是Windows環境下,也就是個滑鼠黨;兩年前換工作開始用linux,也就開始了領略了命令列的強大,無論是直接在命令列組合命令,也還寫幾行簡單的shell指令碼,其能完成的功能往往令人難以置信。
- 關於命令列強大的一個例子:csdn洩露的10個最常用的密碼 awk '{print $3}' www.csdn.net.sql |sort |uniq -c |sort -nr |head (陳碩同學寫的)
- 關於指令碼強大的一個例子:提高分散式環境中程式啟動效能的一個方法
如果說我工作中第一次感覺“哇”是08年左右開始使用perl處理文字 - 發現指令碼原來可以如此強大,自動化那麼多工作;那麼第二次就應當是使用bash - 原來不用寫指令碼也能如此強大。(尤其對原Windows下滑鼠+選單黨來講)
這兩天比較系統的看了下bash reference manual,記錄一下。
一、命令列互動
這裡包括兩個部分,一個是readline支援的命令列編輯功能,有不同的編輯style:emacs和vi模式:
- set -o emacs
- set -o vi
用vi模式的話,使用vi一些常用的命令,編輯起來自然方便,但是需要先escape一下進入操作模式。但是對於平時99%的工作,一些常用的快捷鍵已經足夠滿足了:
- C-a, C-e:移動到行首,行尾
- Alt->, Alt-<-:前移,後移一個單詞 (最好自己定義成右alt,額,好像是我的右alt鍵壞掉了。。。)
- C-b, C-f:前移,後移一個字元
- C-l:清空螢幕
- C-w:刪除前一個單詞
- Alt-d:刪除後一個單詞
- C-d:刪除當前字元
- C-y:貼上前次刪除內容
這些快快捷鍵是readline的預設定義,一般在/etc/inputrc可以找到系統全域性定義,然後個人可以定義:~/.inputrc
另一部分是歷史管理,下面是一些要點:
- 控制歷史的一些變數:HISTSIZE,HISTFILE,HISTFILESIZE
- 設定HISTTIMEFORMAT='%F %T '在歷史中顯示命令執行時間
- C-r:查詢歷史並執行
- history expansion
- !! - 上一條命令
- !preceding - 上一條以preceding開始的命令
- !$ - 上一個命令的最後一個引數
- !n - 第n個命令
- !-n - 倒數第n個命令
二、語法
1. 五種quoting
- \A:轉義,保持字元原意,如果在行末,則表示續行
- 'string':single quoted string,不進行轉義,變數expansion
- “string”:double quoted string,進行轉義,變數expansion
- $'string':訪問一些特殊字元,如$'\a', $'\n'
- $"string":locale specific translation, translated according to the current locale
2. 註釋
以#開頭的行均為註釋,除了第一行:
#!/bin/bash
3. 控制結構
- 簡單命令:cmd
- pipeline: cmd1 | cmd2
- 命令序列:
- cmd1; cmd2: 順序執行兩條命令
- cmd1& cmd2:並行執行兩條命令,其中cmd1在後臺執行
- cmd1 && cmd2: 如果cmd1成功了,執行cmd2
- cmd1 || cmd2:如果cmd1失敗了,執行cmd2
- 迴圈控制
- until test-commands; do consequent-commands; done
- while test-commands; do consequent-commands; done
- for name [ [in [words …] ] ; ] do commands; done
- for (( expr1 ; expr2 ; expr3 )) ; do commands ; done - 例子:for ((i=1; $i < 100; i++)); do echo $i; done
- 條件控制
- if
if的測試表示式有三種情況:-x表示檔案或者變數測試;(==, !=, >, <)表示字串測試;(-gt, -lt, -eq, -ne, -ge)等表示數字測試。
if後測試的表示式可以有三種:
- [[ expression ]]
- [ expression ]
- test expression
-
if test-commands; then consequent-commands; [elif more-test-commands; then more-consequents;] [else alternate-consequents;] fi
- case
case word in [ [(] pattern [| pattern]…) command-list ;;]… esac echo -n "Enter the name of an animal: " read ANIMAL echo -n "The $ANIMAL has " case $ANIMAL in horse | dog | cat) echo -n "four";; man | kangaroo ) echo -n "two";; *) echo -n "an unknown number of";; esac echo " legs."
- select
select name [in words …]; do commands; done select fname in *; do echo you picked $fname \($REPLY\) break; done
- 命令組合
- 新起shell:( list )
- 當前shell:{ list; }
4. 函式
語法 name () compound-command [ redirections ] or function name [()] compound-command [ redirections ] 定義 function reverse() { echo $3-$2-$1 } 呼叫 echo `reverse hello world thanks`
5. 引數
引數有指令碼的引數、函式的引數,都是用$1-$9等來訪問, $0表示指令碼或者函式名字,這些叫做positional parameters,還有一些特殊的引數:$*, $@, $#, $?, $-等等
6. Shell expansion
- brace expansion: echo a{b, c, d}e
- tilde expansion: cd ~; cd ~user/bin
- shell parameter expansion: ${parameter}, , ${parameter:-word}.${parameter:=word}
- command expansion: $(cmd) or `cmd`
- arithmetic expansion: $((1+2*6))
- word splitting
- filename expansion: *.txt
- quote removal
7. Redirection
- >: write stdout to file
- >>: append stdout to file
- &>: write stdout and stderr to file
- &>>: append stdout and stderr to file
- tee: ls | tee ls.txt
8. Variable & array
# variable x=5 echo $x #array: arr[0]=100 echo ${arr[0]} #associate array: declare -A map map[hello]=world echo ${map[hello]}
三、內建命令與變數
builtin的命令,用help就可以全部打出來, 然後逐個help就可以看到大致介紹。
有兩個主要的設定命令:
- set
- shopt
控制bash的各種行為模式。
但有個eval命令我有點搞不清楚:
$ help eval
eval: eval [arg ...]
Execute arguments as a shell command.Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.Exit Status:
Returns exit status of command or success if command is null.
這個,與沒有eval,直接run命令有什麼區別呢?搜了一下,發現這麼個例子:
for i in 2 3 4; do eval a$i=2 eval echo "\$a$i" done
動態組合變數名字並賦值,這個在shell裡直接是做不到的。
另外,三類比較常用的命令:
- 別名:alias, unalias
- job控制:jobs, fg, bg, kill, C-z
- 目錄管理:dirs, popd, pushd
內建的變數,主要用來控制行為,或者暴露資訊,臂長常用的有PATH, PS1, PS2, PWD, HOSTNAME, HISTFILE, IFS, CDPATH(這個貌似可以好好利用一下)
四、常用非內建命令
這裡指的是非bash內建命令,但是linux內建的,或者另外安裝的一些常用命令,非常有效,這裡列幾個自己用的比較多的:
du
df
strace
lsof
ps aux
netstat
grep
find
wget
curl
tr
ssh
sort
uniq
awk
wccut
top
free
vim
p4
perl -pei