歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> FreeBSD Shell的高級功能

FreeBSD Shell的高級功能

日期:2017/2/28 11:28:54   编辑:SHELL編程


由於 shell是Unix下用戶最經常使用的界面,因此熟練掌握必然帶來更高的工作效率。事實上,仍然有很多種技巧,能幫助用戶更方便的使用shell。
1) 命令行使用技巧
一個重要的增強功能是 shell提供的命令行編輯功能,這包括能夠使用上次執行過的指令(命令回溯),對已經輸入的部分進行編輯等等。
注意: shell的這些增強功能是在最新版本(4.2之後)的系統中才加以添加的,因此不再需要額外安裝tcsh或bash。新版的FreeBSD使用tcsh作為基本的csh,而sh的功能也得到了增強。如果是老版本的系統,則需要安裝tcsh作為shell,或者安裝bash,來獲得這些增強功能。
然而,最新的 sh缺省情況下並沒有打開這個功能,因此必須首先打開這個功能,當打開這個功能之後,就能使用方向鍵來回溯執行過的命令,並進行修改。
$ set -o emacs
$ set -o vi
按照習慣的不同,可以選擇 vi風格的編輯方式或emacs風格的方式,而vi風格還能支持vi的鍵盤指令,即在按下Esc鍵之後,使用h、j、k、l四個鍵來移動光標和回溯命令,它的好處是不使用基本鍵盤之外的控制鍵,因而可以適用於任何終端設備,並且進行編輯時手不需離開基本鍵盤,熟練操作之後最為快捷。
最新版本的 csh,即tcsh,缺省就支持命令回溯,但也能使用不同的命令切換編輯風格:
% bind emacs
% bind vi
另一個重要的功能是可以為常用的命令設置別名,簡化用戶輸入,例如:
$ alias ec= “ echo This is a alias ”
$ ec
This is a alias
csh用於方便用戶操作的另一項能力是自動補全命令或文件名的功能,因為FreeBSD下的文件名可能很長,將它們全部輸入比較麻煩。事實上可以輸入部分名字,然後按Tab鍵(在vi風格下是連續兩次按Esc鍵),shell將自動補全文件名的剩余部分。如果已經輸入的這部分名字不能確定具體的命令或文件,那麼shell只將能確定的部分補上,然後響鈴通知使用者繼續輸入以明確具體的文件。
事實上即使在基本的 sh或csh下,也可以使用 “ * ” 等特殊字符,用模式匹配的方式來簡化輸入。
$ cd /usr/loca*
$ pwd
/usr/local
Unix中的多數程序都具備模式匹配的處理能力,而shell的模式匹配功能最為常用。shell可以使用這些特殊模式來配置多個文件,達到簡化操作的目的。如果要熟練掌握Unix,必須掌握模式匹配。
2) 控制功能
Unix的shell不僅僅簡單的接受輸入指令並執行,它更強大的能力是能夠根據條件解釋執行輸入指令。當然,sh和csh對於輸入的解釋語法有所不同,由於在系統中sh最為基本,以下以sh為例,簡單介紹shell的控制功能。
最重要的功能之一是根據條件來判斷是否需要完成某項工作。最簡單的情況下,如果某個程序存在並可以執行,則執行執行這個程序,這種用法在啟動腳本中十分常見。這需要使用邏輯“與”判斷:
$ [ -x /usr/bin/echo ] && /usr/bin/echo “ the program echo is running! ”
the program echo is running!
與此相反的方式是,當條件不成立的時候執行程序,這需要邏輯“或”判斷:
$ [ -f /tmp/somefiles ] || echo “ somefiles is missing! ”
somefiles is missing!
當然,無論哪一種邏輯判斷形式,關鍵點是邏輯判斷本身的語法。一般來講,可以根據文件本身的屬性進行判斷,如上面例子中判斷文件 ” -f ” 是否存在, ” -x ” 判斷文件是否是執行程序,還可以判斷是否為目錄 ” -d ” ,等等。此外,還可以根據字符串來進行判斷,判斷兩個字符串是否相同、甚至比較大小,以及進行數學判斷等等,下面將在介紹其他控制方式時給出一些例子。
更詳細的判斷條件,可以 man test。事實上,判斷語句中的括號[本身就是一個程序,就是test,這個程序根據後面的條件返回一定的結果。因此,完全可以直接根據一個程序的返回結果進行判斷。
使用邏輯與和邏輯或進行邏輯判斷,是邏輯判斷的一種縮略形式,它的好處是能將幾個命令放在一行中。更為標准的方法當然還是使用 if判斷語句。
$ if [ -d /home/user ] ; then echo “ user directory is exist! ” fi
user directory is exist!
此時由於有控制部分,將所有語句都寫在一行上顯然不是好主意, sh允許將這樣一個語句分開完成的機制。
$ if [ ! -d /home/user1 ]
> then
> echo “ user1 directory is not exist! ”
> fi
注意, ” > “ 為 shell的提示符號而不是語句本身,當語句還沒有完成的時候,sh使用提示符 ” > “ ,而不是標准的 ” $ ” ,這個提示符是由環境變量 PS2決定的。這個語句中增加了邏輯非的判斷。
除了根據文件的屬性進行判斷之後,更多的情況下需要判斷字符串是否相同:
QUOTE:$ if [ “ X$TERM ” = “ Xansi ” ]
> then
> echo “ ansi terminal is not supported in FreeBSD! ”
> elif [ “ X$TERM ” > “ Xvt0 ” && “ X$TERM ” < “ Xvt9 ” ]
> then
> echo “ vtXXX serial terminal is ok! ”
> else
> echo “ terminal maybe ok! ”
> fi

上面例子中使用了 if,elif,else等多重判斷形式,甚至還判斷了字符串的大小,判斷$TERM是否是vt系列的終端。
這裡應用了一個小技巧,就是不直接判斷 $TERM本身,而是添加上一個額外的字符 ' X ' ,這是因為 $TERM可能為空變量,這種情況下判斷語句本身就會出現語法錯誤,添加上一個額外的字符就可以避免這個問題。
當然,如果是判斷結果可能是多個字符串之一,那麼就需要使用 case語句:
QUOTE:$ case “ $gateway_enable ” in
> [Yy][Ee][Ss])
> echo “ $gateway is yes ”
> ;;
> *)
> ;;
> esac

這種形式在系統啟動腳本中也非常常見,注意,這裡使用了中括號來忽略變量中的大小寫,事實上這是一種模式匹配的方法,方括號內的任一字符都匹配對應字符。
了解了邏輯判斷語句之後,循環語句也非常自然了,因為循環原則上也是一個邏輯判斷,加上循環的主體而已。
$ COUNT=1; export COUNT
$ while [ $COUNT -lt 10 ]
> do
> echo “ count is $COUNT ”
> COUNT=`expr $COUNT + 1`
> done
這個例子中,我們首先設置了一個環境變量,然後在這個變量小於 10的時候執行循環。當然,循環內部使用了反引號,調用外部程序expr,將該變量自動加一。這就是shell的一個弱點,處理數學計算的時候必須使用外部程序,shell在處理字符串的時候相對簡單,有很多內部功能可以利用,比如直接將兩個變量放在一起,就能完成字符串的合並任務。
如果循環次數比較少,也可以使用這種字符串判斷的方法:
$ while [ “ X$loopflag ” < “ X1111111111 ” ]
> do
> echo “ flag is $loopflag ”
> loopflag=${loopflag}1
> done
這裡每個循環向循環變量後面附加上一個字符,直到循環變量大於某個值為止。
其實,另一種循環方式更為直接,也更方便,就是使用 for語句。
$ for COUNT in 0 1 2 3 4 5 6 7 8 9
> do
> echo “ count is $COUNT ”
> done
通過枚舉的方式把所有循環可能性列出,更為簡單、可靠,而不需要任何其他的外部程序。 這種方法的缺點是如果循環的數量較多就比較麻煩了,如果是這種情況,最好是使用多級循環的方式來解決。
其實 for循環後面的枚舉完全可以和sh的其他功能組合起來,充分發揮功能。
$ for cfile in *c
> do
> echo “ in current directory, there is $cfile ”
> done
上例可以對當前目錄下的所有 c文件進行處理,這就是sh自動將*c這個帶有模式的輸入自動展開為所有匹配的文件名的列表。
$ for cfile in `ls`
> do
> echo “ in current directory, there is $cfile ”
> done
這是另一種形式,使用反引號,讓 sh啟動ls命令,而ls命令的結果作為for的參數。
Copyright © Linux教程網 All Rights Reserved