一 基本觀念
1. 回應目前所使用的shell為何?
$echo $SHELL
2. 通配符號
? 任何一個字符
* 任何字符(一串字符)
[set] 在set中的任何字符
[!set] 不在set中的任何字符
3. 大括弧擴展
{,{,},}
ex. echo b{ed,olt,ar}s 結果列印 beds bolts bars
ex. echo b{ar{d,n,k},ed}s 結果列印bards barns barks beds
ex. echo {d..h} 結果看到 d e f g h
至少要有一個逗號 否則所產生的單字會維持原狀 ex. b{o}lt 還是被當成b{o}lt
4. 背景執行
指令後面加&
5. 檢視背景執行
$jobs
6. nice command
$nice command
command 以比較低的優先權處理
7. 特殊字符與加引號
~ 主目錄
` 命令替換(舊式)
# 註解
$ 變數表示示
& 背景工作
* 字串通配符
( 啟動subshell
) 終止subshell
\ 引述下一個字符
| 導管
[ 起始字符集通配符
] 終止字符集通配符
{ 起始命令區塊
} 終止命令區塊
; shell命令之區隔符
' 強引號
" 弱引號
< 輸入轉向
> 輸出轉向
/ 路徑名稱之目錄區隔符
? 單字符通配符
! 管線之邏輯NOT算符
8. 去除特殊字符的字面意義
a.)加單引號(quoting)---
去除特殊字符的字面意義
ex. $echo '2 * 3 > 5 is a valid inequality.'
b.)以倒斜線規避
ex. $echo 2 \* 3 \> 5 is a valid inequality.
9. 控制鍵
控制鍵 相應的stty名稱 功能
^C intr 結束現行命令
^D eof 結束輸入
^\ quit 結束現行命令,如果CTRL-C管用的話
^S stop 停止輸出到螢幕上
^Q 開始輸出到螢幕上
^?或DEL erase 刪除最後一個字符
^U kill 刪除整個命令列
^Z/^Y susp 暫停現行的命令
^W werase
^R rprnt
^O flush
^V lnext
可以使用stty -a 查看設定
二 編輯命令列
emacs 編輯模式
1. 基本指令
^B 將游標往後(backward)移一個字符(不會進行刪除動作)
^F 將游標往前(forward)移一個字符
DEL 往後(backward)刪除一個字符
^D 往前(forward)刪除一個字符
2. 單字處理命令
ESC-B 將游標往後(backward)移動一個單字
ESC-F 將游標往前(forward)移動一個單字
ESC-DEL 往後刪除(kill)一個單字
ESC-^-H 往後刪除一個單字
ESC-D 往前刪除一個單字
^-Y 取回(yank)上一次所刪除的項目
3. 列處理命令
^-A 移到列的開頭
^-E 移到列的結尾
^-K 往前刪除一整列
4. 在歷程檔中遊走
^-P 移到上一頁
^-N 移到下一頁
^-R 往回搜尋
ESC-< 移到歷程的第一列
ESC-> 移到歷程的最後一列
5. 文字補全
tab 試圖進行一般的補全功能
ESC-? 列出可能的補全結果
ESC-/ 試圖補全檔案名稱
^-X/ 列出可能的『檔案名稱』補全結果
ESC-~ 試圖補全用戶名稱
^-X~ 列出可能的『用戶名稱』補全結果
ESC-$ 試圖補全變數
^-X$ 列出可能的變數補全結果
ESC-@ 試圖補全主機名稱
^-X@ 列出可能的『主機名稱』補全結果
ESC-! 試圖補全命令
^-X! 列出可能的『命令』補全結果
ESC-TAB 試圖以歷程紀錄(history list)中之前所鍵入的命令進行補全
6. 雜項命令
^-J 同RETURN
^-L 清除螢幕,將現行(current)列置於螢幕頂端
^-M 同RETURN
^-O 同RETURN,但會接著顯示命令歷程中的下一列
^-T 將標點兩邊的字符對調,並將標點向右移動一個位置
^-U 刪除從列的開頭到標點為止的部份
^-V 未下一個字符加上引號(規避該字符的特殊意義,如果有特殊意義的話)
^-[ 同ESC(適用於大多數鍵盤)
^-C 將標點右邊的單字(word)換成大寫字母開頭
^-U 將標點右邊的單字全部換成大寫字母
^-L 將標點右邊的單字全部換成小寫字母
ESC-. 在標點右邊插入上一道命令列的最後一個單字
ESC-_ 同ESC-.
vi 編輯模式
0. vi輸入模式的編輯命令
del 刪除前一個字
^-w 刪除前一個單字
^-v 為下一個字符加上引號
esc 進入控制模式
以下所有命令都可以前置一個數字(n)做為重複次數
1. 簡單的控制模式命令
h 往左移一個字 (與編輯時^+H有關)
l 往右移一個字
w 往右移一個單字
b 往左移一個單字
W 移到下一個非空白單字的開頭
B 移到前一個非空白單字的開頭
e 移到現行單字的末端
E 移到現行非空白單字的末端
0(zero) 移到一列之首
^ 移到一列之第一個非空白字符
$ 移到一列的的末端
2. 鍵入和更改文字
i 字前插入文字(插入)
a 字後插入文字(添加)
I = 0i 列首插入文字
A = $a 列尾插入文字
R 覆蓋既有文字(Replace in edit mode)
(n)r 覆蓋既有文字(command)
3. 刪除命令
用c替代d,會在做完刪除後進入輸入模式
dh 往左刪除一個字
dl 往右刪除一個字
db 往左刪除一個單字
dw 往右刪除一個單字
dB 往左刪除一個非空白單字
dW 往右刪除一個非空白單字
d$ 一直刪除到行尾端
d0 一直刪除到行開端
D = d$
dd = 0d$
C = c$
cc = 0c$
X = dh
x = dl
u undo(undelete)
. 重複上次文字修改命令
y(yank) 擷取
p 文字插入在字的右邊
P 文字插入在字的左邊
4. 在歷史檔中遊走
k = - 往後移動一列
j = + 往前移動一列 (與編輯時^+J有關)
G = gg 移動到重複次數所指定的命令列
/string 往後搜尋字串string
?string 往前搜尋字串string
n 依上次搜尋方向重複搜尋
N 依上次搜尋反方向重複搜尋
5. 尋找字符命令
fn 向右移動到下一個n所在位置
Fn 向左移動到前一個n所在位置
tn fn+移回一格
Tn Fn+往前移一格
|
三. 訂製你的環境
1. 啟動檔: .bash_profile .bash_logout .bashrc
登入系統檔案尋找順序(找不到檔案便會往下一個檔案找): .bash_profile -> .bash_login -> .profile
離開login shell :會執行.bash_logout
.bash_profile只會被login shell 所讀取與執行。如果在命令列上以鍵入bash的方式啟動一個新的shell(一個shushell),它會試圖從.bashrc檔中讀取命令。
2. 別名:
alias name='command' or command //=兩邊不能有空格
可以替別名取另一個別名,也就是別名可以遞迴定義。
alias listfile=ls
alias ls=listfile //那麼別名listfile將會被略過不計。
bash隱晦功能:如果一個別名的值(等號的右邊部分)是以一個空格結束的,那麼bash便會對命令列的下一個單字進行別名替換。要讓別名的值以空格結束,得要為它加上引號。
alias name 或 alias : 會列出別名設定。
3. 選項:
set -o optionname (開啟option) 和 set +o optionname(關閉option)
3.1 shopt
-p 列出可設定的shell選項以及他們目前的設定值。
-s 設定(set)或開啟每個選項名稱。
-u 取消(unset)或關閉每個選項名稱。
-q 抑制正常輸出;傳回狀態會指出一個變數是否有被設定。
-o 允許選項名稱的值成為set命令以-o選項所定義的值。
4. shell變數:
varname='value' or value //=兩邊不能有空格
變數使用$varname
查看變數值 可使用echo $varname
4.1 變數以及加引號
雙引號裡的特殊字符會被shell解釋
單引號裡的特殊字符完全不會遭到shell的解釋
4.2 內建變數
4.2.1 編輯模式變數
4.2.2 郵件變數
MAIL 郵件檔的名稱,用以檢查有無新收到的郵件
郵件檔 /usr/mail/yourname
只要設定 MAIL=/usr/mail/yourname 就行了。
MAILCHECK 多久檢查一次新郵件,以秒為單位(預設60秒)
MAILPATH 郵件檔名單,以冒號(:)為分隔符,用來檢查新收到的郵件。
ex. MAILPATH=/usr/mail/you/martin:/usr/mail/you/geoffm:/usr/mail/you/paulr
MAILPARH="\
/usr/mail/you/martin?you have mail from Martin.:\
/usr/mail/you/geoffm?Mail from Geoff has arrived.:\
/usr/mail/you/paulr?There is new mail from Paul."
$_ 顯示幕前的郵件檔名稱
4.2.3 提示變數
分別存放在PS1 PS2 PS3 PS4
提示字串的制定命令
\a ASCII的響鈴(bell)字符(007)
\A 採用24小時制,以HH:MM的格式來顯示現在的時間
\d 以Weekday Month Day的格式來顯示日期
\D{format} format會被傳入strftime(3),所產生的結果會被插入提示字串;如果format為空值,則會以語系特定的格式來顯示時間
\e ESC(033)
\H 主機名稱
\h 主機名稱中第一個.之前的部分
\j shell目前所控管的工作數量
\l shell之終機端名稱的基本名稱(basename)
\n LR+LF
\r LR
\s shell的名稱
\T 採用12小時制,以HH:MM:SS的格式來顯示現在的時間
\t 以HH:MM:SS的格式來顯示現在的時間
\@ 採用12小時制,以am/pm的格式來顯示現在的時間
\u 現行使用者的用戶名稱
\v bash的版本 ex.2.00
\V bash的發行版本;版本和修補次數 ex.2.00.0
\w 現行工作目錄
\W 現行工作目錄的基本名稱(basename)
\# 現行命令的命令編號
\! 現行命令的歷程編號
\$ 如果有效的UID是0,就顯示一個"#"符號,否則就顯示一個"$"符號
\nnn 八進制的字符碼
\\ 顯示一個到斜線
\[ 非列印(non-printing)字符序列的開頭,像是終端機的控制序列
\] 非列印(non-printing)字符序列的結尾。
4.2.4 命令的搜尋路徑
在.bash_profile加入PATH: PATH=$PATH:"/home/you/bin"
4.2.5 將命令的路徑存入雜湊表
hash 查看雜湊表內容
hash -r 移除hash的一切
hash -d name 移除特定的命令名稱
hash -p namepath 加入特定的命令路徑
使用set 指定hashall 選項開關hash
4.2.6 目錄的搜尋路徑和變數
CDPATH 值如同PATH
空字串代表現行目錄
4.2.7 雜項變數
HOME 你的主機(登入)目錄名稱
SECONDS shell被調用之後所持續的秒數
BASH 你所執行之shell的路徑名稱
BASH_VERSION 你所執行之shell的版本編號
BASH_VERSINFO 你所執行之shell的版本資訊陣列
PWD 現行目錄
OLDPWD 執行上一次cd命令之前所在的目錄
5. 定製與子行程
5.1 環境變數
export varnames
export or export -p 察看環境變數
TERM=trythisone emacs filename
四. shell 程式設計基礎
1. shell 命令稿與函式
執行script方法:
1. source scriptname
2. 鍵入檔案名稱+enter
./scriptname :相當於鍵入命令稿的絕對路徑
透過名稱調用命令稿之前需要先賦予它執行權
差異:
source scriptname shell: ---->--script-->----> 在同一個shell上執行script
scriptname shell: ----> ----> shell等待subshell執行完script後繼續執行
subshell: --script--> 在subshell上執行script
scriptname& shell: ---->...........----> subshell執行同時shell繼續執行(subshell在背景執行)
subshell --script--> 在背景subshell執行script
1.1 函式
表示方式:
1.
function functname
{
shell commands
}
或
2.
functname ()
{
shell commands
}
可以使用unset -f functname 刪除某個函式的定義
declare -f :查看登入時間定義了那些函式
declare -F :僅查看函式的名稱
函式與script差異: 1. 函式並不會以名子來調用script那樣被執行在另一個行程中,執行一個函式的語意比較像是登入系統時,.bash_profile檔所做的事或是像以source命令來調用任何script。
2. 函式與script同名時,函式具有優先執行的權利
各種命令優先權:
1. 別名
2. function 以及 if 和for 之類的關鍵字
3. 函式
4. 內建命令,像是cd 和type
5. script和可執行的程式,shell會根據PATH環境變數裡所列舉的目錄來搜尋他們
如果名稱相同,別名會比函式和script具有更高的執行優先權。可以使用command,builtin 和 enable等內建命令來改變他們優先執行順序。
type name : 解釋bash命令方式
type -a name 查看name所有定義
type -p name 查看限制為可執行檔或shell script
type -P name 查看限制為可執行檔或shell script 即使-t選項回傳值不是file
type -f name 查看只支援關鍵字、檔案以及別名。
type -t name 只查看描述單字alas, keyword, function, builtin 或file
-t可以和其他選項一起使用
2. shell變數
可以使用$VAR 取得值
可以透過export讓子行程知道
2.1 位置參數
唯讀不能指定新值
1 2 3等等: 他們的值$1 $2 $3表示第一個到第三個輸入參數
0 值$0 : 代表script file name
* 和 @ : 這2個特殊變數包含了所有的位置參數(位置參數0除外),兩者之間的差異相當微妙但很重要,而且只有當他們被雙引號刮住時,才會凸顯此一差異。
"$*" : 是一個包含所有位置參數的單一字串,並以環境變數IFS(internal field separator)中的第一個字符做為位置參數的分隔符;IFS的預設通常是一個空格、跳格或換行符號。
"$@" : 相當於"$1" "$2" ..."$N" N代表參數數目相當於N個以雙引號刮住的字串,並以空格為分隔符
# : 存放位置參數的數目
2.1.1 函式中的位置參數
-----------------------------------
| ascript(script) |
| ------------- |
| | $var1 | |
| ------------- |
| ------------- |
| | $0 | |
| ------------- |
| ------------- |
| | $1 | |
| ------------- |
| ------------- |
| | $2 | |
| ------------- |
| --------------------- |
| | 函式 afunc | |
| | ------------- | |
| | | $1 | | |
| | ------------- | |
| | ------------- | |
| | | $2 | | |
| | ------------- | |
| --------------------- |
-----------------------------------
$var1 $0 在ascript(script)和函式afunc都看的到
script的$1 $2 只有在script看的到
函式的$1 $2 只有在函式看的到
2.2 函式裡的區域變數
local var #設定為區域變數
2.3 具引號的$@和$*
為什麼"$*"中的元素要以IFS的第一個字符做為分隔符號,而不使用空格就好?這是為了讓你的輸出具有彈性。
為什麼"$@"的行為就好像是N個被加上雙引號的字串?這是為了讓你能再以分開的值來使用他們。
2.4 變數的另一種語法
除了$varname 外,還有${varname} 這個更一般化之語法的簡單形式。
為什麼會有兩種語法?
1. 如果你的程式碼參用到九個以上的位置參數時你必須用${10}來表示第十個參數,不可以用$10
2. 如果想要在變數後面加一個底線之類符號
3. 字串算符
字串算符能讓你作以下幾件特別的事:
確定變數存在與否(亦既有被定義而且其值不是空的)
為變數設定預設值
捕捉因變數未被設定所導致的錯誤
移除變數值中與樣式相符的部份
3.1 字串算符的語法
字串算符的語法,基本上就是將具運算能力的特殊字符擺在變數名稱與右括號之間,而算符所需要的任何引數則會擺在算符的右邊。
${varname:-word} : 若varname存在而且不是空的,則傳為它的值;否則傳回word。
目的:若此變數沒有被定義,則傳回一個預設值。
ex.: 若count沒有定義 ${count:-0}的求值結果為0
${varname:=word} : 若varname存在而且不是空的,則傳回他的值;否則就把他設成word,然後傳回它的值。位置參數和特殊參數不能以這種方式指定。
目的:若某個變數沒有被定義,則為他設定一個預設值。
ex.: 若count沒有定義 ${count:=0} 會把count設成0。
${varname:?message} : 若varname存在而且不是空,則傳回它的值;否則印出varname:message,並放棄現行的命令或命令稿 (只適用於以非互動方式操作的shell)。若省略message則會產生parameter null or net set
目的:捕捉因變數未定義所導致的錯誤。
ex.: 若count沒有定義 ${count:?"undedined!"}會顯示 count:undefined!
${varname:+word} 若varname存在而且不是空的,則傳回word;否則傳回空值(null)。
目的:測試某個變數存在與否。
ex.: 若count有定義 ${count:+1}會傳回1(代表此事為真)。
${varname:offset:length} :進行子字串的擴展(substring expansion)。它會傳回$varname中開始位置為offset,字符個數為length的子字串。
$varname中第一個字符的位置編號為0。若省略length,這個子字串將會從offset開始,一直延續到$varname的末端。
如果offset小於0,那麼位置會從$varname的末端開始算起。
如果varname是@,哪麼length就是從參數offset開始算起之位置參數的數目。
目的:傳回某個字串的一部分(子子串或切片)
ex.若count被設成frogfootman,則${count:4}會傳回footman。而${count:4:4}會傳回foot。
3.2 樣式以及樣式比對
${variable#pattern} 如果pattern與變數值的開頭相符就刪除相符的部分(取最短者),並傳回變數其餘的部份。
${variable##pattern} 如果pattern與變數值的開頭相符就刪除相符的部分(取最長者),並傳回變數其餘的部份。
${variable%pattern} 如果pattern與變數值的結尾相符就刪除相符的部分(取最短者),並傳回變數其餘的部份。
${variable%%pattern} 如果pattern與變數值的結尾相符就刪除相符的部分(取最長者),並傳回變數其餘的部份。
${varable/pattern/string}
${varable//pattern/string} 在variable中符合pattern的部份(取最常者)會被取代成string。
如果是第一種形式,只有的一個相符的部份會被取代。
如果是第二種形式,所有相符的部份都會被取代。
如果pattern是以一個#開始的,它就必須比對變數的開頭。
如果pattern是以一個%開始的,它就必須和變數的結尾進行比對。
如果string是空的,符合的部份會被刪除。
如果variable是@或*,則會依序對每個位置參數作此操作。
3.3 長度算符
${#varname} 它會傳回字符串之變數值的長度。
3.4 經延伸的pattern比對算符
*(patternlist) 所指定的pattern出現零或多次,代表符。
+(patternlist) 所指定的pattern出現一或多次,代表符。
?(patternlist) 所指定的pattern出現零或一次,代表符。
@(patternlist) 所指定的pattern出現一次,代表符。
!(patternlist) 相符於任何pattern,但所指定的樣式除外。
4. 命令替換
$(UNIX Command)
五. 流程控制
1. if/else
if condition
then
statements
[elif condition
ethen statements...]
[else
statements]
fi
1.1 結束狀態
0 通常代表沒問題的結束狀態。 其他編號(1~255)通常代表錯誤。
如果結束狀態=0, condition 會被判定為真; 若為其他值則判定為否。
$? 最後一個執行之命令的狀態。
1.2 return N
return 只能用在函式和以source 執行的shell script。相對而言exit N 會結束整個shell script。
1.3 合併結束命令
statement1 && statement2 執行statement1,如果它的結束狀態是0(true),繼續執行statement2。
statement1 || statement2 執行statement1,如果它的結束狀態不是0(true),繼續執行statement2。
1.4 條件測試
[...]
[[...]] 如同[...]但不會對括符裡的單字進行單字分離和路徑名稱擴展的動作。
1.4.1 字串比較
字串比較算符
算符 若...為真
==================================================================
str1=str2 str1與str2相符
str1!=str2 str1與str2不相符
str1<str2 str1小於str2
str1>str2 str2大於str2
-n str1 str1不是空的
-z str1 str1是空的
1.4.2 檔案屬性檢查
檔案屬性算符
算符 若...為真
==================================================================
-a file file 存在
-d file file 存在,而且是一個目錄。
-e file file 存在;如同-a
-f file file 存在,而且是一個普通檔案(並非目錄或其他特殊檔)
-r file 擁有file的讀取權
-x file 擁有file的執行權,或目錄的搜尋權
-N file 自從上次讀取後file已被修改過
-O file 擁有file的所有權
-G file file的群組識別碼符合你的群組識別碼,或是你的群組識別碼中的一個(如果你同時隸屬於多個群組)
file1 -nt file2 file1比file2還新
file1 -ot file2 file1比file2還舊
if [ condition ] && [ condition ]; then
if command && [ condition ]; then
1.5 整數條件句
算術測試算符
測試 比較
=================================================================
-lt 小於
-le 小於或等於
-eq 等於
-ge 大於或等於
-gt 大於
-ne 不等於
2. for
for 迴圈可讓已以固定的次數<重複執行某個區段的程式碼
語法:
for name [in list ]
do
用來處理 $name 的述句
done
list是一份名單(如果省略 in list,這份名單會被預設為"$@")
沒有留言:
張貼留言