UNIX再学习 -- shell编程
生活随笔
收集整理的這篇文章主要介紹了
UNIX再学习 -- shell编程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
UNIX環境高級編程看了三章,遇到不少重定向等shell命令。本想到Linux時再講,看來有必要提前了。之前有看過一本《嵌入式Linux軟硬件開發詳解》這本書里有簡單介紹了一部分shell常用命令,就結合它來簡單介紹下shell編程。畢竟沒有詳細看過shell相關的書籍,等以后看過了再詳細講吧。
首先,推薦一款 shell 在線工具
擴展學習:Shell 教程
相關書籍:Linux命令行與Shell腳本編程大全
常用快捷鍵:
Ctrl+C強制終止當前命令 Ctrl+L 清屏,相當于clear Ctrl+U 刪除或者剪切光標之前的所有命令,比退格方式更快捷 Ctrl+K 刪除或者剪切光標之后的所有命令 Ctrl+Y 粘貼Ctrl+U或者Ctrl+K剪切的內容 Ctrl+R 實現搜索歷史命令,先輸入Ctrl+R,然后回車再輸入需要搜索的歷史命令 Ctrl+D 退出當前終端 Ctrl+Z 暫停命令并且放入后臺,不能經常使用 Ctrl+S 暫停屏幕輸出 Ctrl+Q 恢復屏幕輸出
一、bash shell 簡介
1、在UNIX基礎知識這章中,有簡單介紹shell:
shell 是一個命令行解釋器,它讀取用戶輸入,然后執行命令。shell 用戶輸入通常來自終端(交互式 shell),有時則來自于文件(稱為 shell 腳本)。UNIX系統中常見的 shell: Bourne shell ?路徑:/bin/sh?
Bourne-again shell ?路徑:/bin/bash
C shell ?路徑:/bin/csh?
Korn shell ?路徑:/bin/ksh?
TENEX C shell ?路徑:/bin/tcsh
其中的?Bourne-again shell 就是我們要講的簡稱 bash shell,它是 GNU shell,所有 Linux 系統都是提供這種 shell 。它的設計遵循 POSIX 標準,同時保留了與 Bourne shell 的兼容性。它支持 C shell 和 Korn shell 兩者的特色。 系統從口令文件中相應的用戶登錄項的最后一個字段中了解到應該為該登錄用戶執行哪一個 shell。 我用的虛擬機是 Ubuntu 12.04,內核是 Linux 3.2.0,使用 root 超級用戶。查看用戶登錄文件 /etc/passwd? 查看 /etc/passwd : root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/bin/sh man:x:6:12:man:/var/cache/man:/bin/sh 可以看到:root:x:0:0:root:/root:/bin/bash ?所以,我所執行的是 bash shell 其他字段含義,可參看:UNIX再學習 -- 再識
2、與其他 shell 比較
bash shell 是 Linux 操作系統中標準的 shell,當前幾乎所有 Linux 版本都使用 bash shell 作為系統管理的核心,相比其他 shell ,bash shell 具有更加強大的功能:(1)命令記憶功能
我們通過按鍵盤上的 【上下鍵】 可以查看到之前使用過的指令。每次登陸后執行的指令都被暫存在緩沖區中,成功退出系統后,該指令便會記錄到 bash_history 文件當中。通過這一功能,我們可以很方便地修改錯誤的執行命令。(2)命令與文件補全功能
使用此功能,我們可以少打很多字并且確保輸入的數據是正確的。【Tab】 接在一串命令的第一個字的后面,為“命令補全”;【Tab】接在一串命令的第二個字的后面,則為“文件補全”。通過這一功能,我們可以快速查看或匹配當前目錄下相關命令或文件。(3)命令別名設置功能
Linux 系統中包含有千差萬別的命令名及參數,既不方便使用也不方便管理。bash shell 中提供了利用 Alias 自定義命令別名的功能。(4)編程功能
shell 不僅可以作為命令解釋器用來定制工作環境,還可以作為一門高級編程語言編寫執行用戶指令的腳本,從而更加快速有效地處理復雜的任務。二、bash shell 常用命令
當用戶登錄到 Linux 系統時,便開始于 bash 進行互動,一直到用戶注銷為止(以后講 Linux啟動時會詳細介紹這部分)。如果是普通用戶,則 bash 的默認提示符為“$”(代表普通用戶),如果是 root 超級用戶,提示符則變為“#”。用戶與系統互動的過程便是通過在提示符后面輸入操作命令來完成的。 為了加強 shell 的處理能力,bash shell 除本身內置一部分命令,如 cd 等,還增加了對外部應用命令的支持,如 ls、ps等。 在 shell 的命令提示符后面輸入的命令,如果是 bash shell 內置的命令,則有它自己負責回應;如果是外部應用命令,則 shell 會找出對應的外部應用程序,然后將控制權交給內核,由內核執行該應用程序之后再講控制權交回給 shell。 常見命令如下: 這部分更多內容,搜索:Linux命令大全??Shell內建命令1、type
命令格式:type 參數命令 功能:判斷一個命令是內置命令還是外部命令 選項: -t:輸出“file”、“alias”或者“builtin”,分別表示給定的指令為“外部指令”、“命令別名”或者“內部指令”; -p:如果給出的指令為外部指令,則顯示其絕對路徑; -a:在環境變量“PATH”指定的路徑中,顯示給定指令的信息,包括命令別名。 實例: # type ls ls 是 `ls --color=auto' 的別名# type -t ls alias# type -a ls ls 是 `ls --color=auto' 的別名 ls 是 /bin/ls可以看出,ls為命令別名# type cd cd 是 shell 內嵌# type -t cd builtin# type -a cd cd 是 shell 內嵌可以看出,cd為內部命令# type which which 是 /usr/bin/which# type -t which file# type -p which /usr/bin/which# type -a which which 是 /usr/bin/which which 是 /bin/which可以看出,which為外部命令通過,type 命令的用法,我們可以知道每個命令是否為 bash 內置命令。此外,使用 type 搜索后面的名稱時,如果后接的名稱不能以執行文件的狀態找到,那么該名稱不會顯示。2、echo
命令格式:echo arg 功能:在屏幕上顯示出有 arg 指定的字符串 實例: 簡單顯示: # echo hello hello創建shell腳本: gedit hello.sh #!/bin/bash echo "hello world!"執行 ./hello.sh bash: ./hello.sh: 權限不夠 添加權限:chmod +x *.sh 或者 chmod 777 *.sh# ./hello.sh hello world! 擴展部分:echo命令選項: ? ?-e:激活轉義字符。
使用-e選項時,若字符串中出現以下字符,則特別加以處理,而不會將它當成一般文字輸出: \a 發出警告聲; \b 刪除前一個字符; \c 最后不加上換行符號; \f 換行但光標仍舊停留在原來的位置; \n 換行且光標移至行首; \r 光標移至行首,但不換行; \t 插入tab; \v 與\f相同; \\ 插入\字符; \nnn 插入nnn(八進制)所代表的ASCII字符; 實例: # echo -e "\e[1;31mThis is red text\e[0m" This is red text# echo -e "\e[1;42mGreed Background\e[0m" Greed Background
3、export
這部分再講環境變量時講過了,參看:UNIX再學習 -- 環境變量命令格式1:export variable 功能:shell 可以用 export 把它的變量向下帶入 子 shell,從而讓子進程繼承父進程中的環境變量。但子 shell 不能用 export 把它的變量向上帶入父進程。 實例: # export HELLO="hello" # echo $HELLO hello 命令格式2:export 功能:顯示當前所有環境變量及其內容。 實例: # export declare -x COLORTERM="gnome-terminal" declare -x DBUS_SESSION_BUS_ADDRESS="unix:abstract=/tmp/dbus-Kss6b0aquA,guid=297ad74aed4e17b7f89f981d0000003c" declare -x DEFAULTS_PATH="/usr/share/gconf/ubuntu-2d.default.path" declare -x DESKTOP_SESSION="ubuntu-2d" declare -x DISPLAY=":0" declare -x GDMSESSION="ubuntu-2d" declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated" declare -x GNOME_KEYRING_CONTROL="/tmp/keyring-qyAxFa" declare -x GPG_AGENT_INFO="/tmp/keyring-qyAxFa/gpg:0:1" declare -x GTK_IM_MODULE="ibus" declare -x HOME="/root" .....4、readonly
命令格式1:readonly variable 功能:將一個用戶自定義的 shell 變量標識為不可變 實例: # export HELLO="hello" # readonly HELLO="hello" # export HELLO="hello" world bash: HELLO: 只讀變量 # unset HELLO bash: unset: HELLO: 無法反設定: 只讀 variable 命令格式2:readonly 功能:顯示出所有只讀的 shell 變量 實例: # readonly declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath" declare -ir BASHPID declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="24" [3]="1" [4]="release" [5]="i686-pc-linux-gnu")' declare -ir EUID="0" declare -ir PPID="2590" declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor" declare -ir UID="0"5、read
命令格式:read variable 功能:從標準輸入設備讀入一行,分解成若干行,賦值給 shell 程序定義的變量。 實例:創建shell腳本: gedit hello.sh #!/bin/bash echo -e "Please enter: \c" read x echo "you enter: $x"執行腳本: # ./hello.sh Please enter: hello world! you enter: hello world!再例如,終端輸入密碼時候,不讓密碼顯示出來,可創建如下腳本: 方法一: 創建腳本: #!/bin/bash read -p "輸入密碼:" -s pwd echo echo password read, is "$pwd"執行腳本: ./hello.sh 輸入密碼: password read, is 12345 方法二: 創建腳本: #!/bin/bash stty -echo read -p "輸入密碼:" pwd stty echo echo echo 輸入完畢執行腳本: ./hello.sh 輸入密碼: 輸入完畢注意: stty -echo? 選項 -echo 禁止將輸出發送到終端,而選項 echo 則允許發送輸出。
6、env
命令格式:env 功能:顯示環境變量及其內容。 實例: # env LC_PAPER=en_US.UTF-8 LC_ADDRESS=en_US.UTF-8 SSH_AGENT_PID=1749 LC_MONETARY=en_US.UTF-8 GPG_AGENT_INFO=/tmp/keyring-qyAxFa/gpg:0:1 TERM=xterm SHELL=/bin/bash .....7、set
命令格式:set 功能:顯示所有變量及其內容 實例: # set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=() BASH_SOURCE=() .....8、unset
命令格式:unset 功能:從環境中刪除變量或函數。這個命令不能刪除 shell 本身定義的只讀變量。 實例: # export HELLO="hello" # unset HELLO # echo $HELLO #9、grep
命令格式:grep 參數 string 目標文件 功能:在指定文件一堆文件中查找一個特定的字串并將字串所在行輸出到終端或平臺。 參看:grep 命令 選項: -a 不要忽略二進制數據。 -A<顯示列數> 除了顯示符合范本樣式的那一行之外,并顯示該行之后的內容。 -b 在顯示符合范本樣式的那一行之外,并顯示該行之前的內容。 -c 計算符合范本樣式的列數。 -C<顯示列數>或-<顯示列數> 除了顯示符合范本樣式的那一列之外,并顯示該列之前后的內容。 -d<進行動作> 當指定要查找的是目錄而非文件時,必須使用這項參數,否則grep命令將回報信息并停止動作。 -e<范本樣式> 指定字符串作為查找文件內容的范本樣式。 -E 將范本樣式為延伸的普通表示法來使用,意味著使用能使用擴展正則表達式。 -f<范本文件> 指定范本文件,其內容有一個或多個范本樣式,讓grep查找符合范本條件的文件內容,格式為每一列的范本樣式。 -F 將范本樣式視為固定字符串的列表。 -G 將范本樣式視為普通的表示法來使用。 -h 在顯示符合范本樣式的那一列之前,不標示該列所屬的文件名稱。 -H 在顯示符合范本樣式的那一列之前,標示該列的文件名稱。 -i 胡列字符大小寫的差別。 -l 列出文件內容符合指定的范本樣式的文件名稱。 -L 列出文件內容不符合指定的范本樣式的文件名稱。 -n 在顯示符合范本樣式的那一列之前,標示出該列的編號。 -q 不顯示任何信息。 -R/-r 此參數的效果和指定“-d recurse”參數相同。 -s 不顯示錯誤信息。 -v 反轉查找。 -w 只顯示全字符合的列。 -x 只顯示全列符合的列。 -y 此參數效果跟“-i”相同。 -o 只輸出文件中匹配到的部分。常用方法: 當前所有含 hello 的文件 # grep "hello" * -Rn 當前所有不含 hello 的文件 # grep "hello" * -vn10、wc
命令格式:wc 參數文件1 文件2 .... 功能:統計指定文件中的字節數、字數、行數并將統計結果顯示輸出。 選項: -c或--bytes或——chars:只顯示Bytes數; -l或——lines:只顯示列數; -w或——words:只顯示字數。 實例: # wc aio.h 246 967 7502 aio.h 分別是: 列數 字數 字節數 文件名三、重定向與管道
shell 命令在執行時,會自動打開三個標準文件,標準輸入文件(stdin,一般對應終端的鍵盤),標準輸出文件(stdout)和標準出錯輸出文件(stderr,對應終端的屏幕),參看:C語言再學習 -- 文件 在實際應用中,這三個文件常常需要按照新的格式進行定向,從其他文件中導入內容或將內容導出到其他文件中,這個過程就是重定向;使內容按照一定格式輸出,這就是管道。1、重定向
重定向可分為輸出重定向、錯誤重定向與輸入重定向(1)輸出重定向
通過重定向符“>”或“>>”將命令的標準輸出重新定向到指定文件中。 一般形式:命令 > 文件名 “>”與“>>”都能將內容重新寫入到文件中,但如果文件中有內容,執行“>”后新的內容將會覆蓋掉原來的內容,而“>>”則是將新的輸出內容附加到原來內容的結尾。 實例: 新建text.txt # touch text.txt將ps內容輸出到 text.txt 文件中 # ps > text.txt 查看 text.txt 內容 # cat text.txt PID TTY TIME CMD2600 pts/0 00:00:00 bash3231 pts/0 00:00:00 ps如果再將 ls內容使用 ">" 輸出到 text.txt 文件中 # ls > text.txt 再查看 text.txt內容,則覆蓋掉了原來的內容 # cat text.txt text.txt如果再將 ps內容使用 ">>" 輸出到 text.txt 文件中 # ps >> text.txt 再查看 text.txt內容,則附加到原來的內容的結尾 # cat text.txt text.txtPID TTY TIME CMD2600 pts/0 00:00:00 bash3236 pts/0 00:00:00 ps(2)錯誤重定向
通過重定向符“2>”或“2>>”將命令的標準錯誤輸出重定向到指定文件中。 “2>”和 “2>>”區別同上面的“>”和“>>”這里就不做說明了。 一般形式: 命令 2> 文件名 命令 2>> 文件名 實例: hello沒有這個文件,查看會出錯 # cat hello cat: hello: 沒有那個文件或目錄將錯誤保存到 text.txt 文件中 # cat hello 2> text.txt # cat text.txt cat: hello: 沒有那個文件或目錄(3)輸入重定向
通過重定向符“<”將命令的標準輸入重新定位到指定文件中。一般形式:命令 < 文件名實例:查看腳本 # cat sh.sh echo “you working directory is $(pwd)” echo "the time is $(date)"shell命令解析程序從腳本程序 sh.sh 中讀取命令行并加以執行 # bash < sh.sh “you working directory is /home/tarena/project/c_test” the time is Wed Mar 22 10:07:45 CST 20172、管道
在 Linux 下我們可以采用管道操作符 “|”來連接多個命令或進程,在連接的管道線兩邊,每個命令執行時都是一個獨立的進程。前一個命令的輸出正是下一個命令的輸入。這些進程可以同時進行,而且隨著數據流在它們之間的傳遞可以自動地進行協調,從而能夠完成較為復雜的任務。管道我們也并不陌生,之前講 xargs 用法時有用到的。 參看:C語言再學習 -- Xargs用法詳解 一般形式:[命令1] | [命令2] | [命令3] 實例: ls 命令查看 # ls sh.sh text.txt可以可以指定查找腳本文件 # ls | grep *sh sh.sh四、shell簡單應用
shell 除了作為命令編譯器用于管理命令外,還可以用來進行程序設計。它提供了定義變量和參數的手段以及豐富的過程控制結構。使用 shell 編程類似于使用 DOS 中的批處理文件,稱為 shell 腳本,又叫 shell 程序 或 shell 命令文件。1、基本用法
(1)開頭
程序必須以下面的行開始,且必須放在文件的第一行。 #!/bin/bash符號“#!”用來告訴系統它后面的參數是用來執行該文件的程序,在這個例子中使用 /bin/bash 來執行程序。 而 /bin/bash 正是 bash?shell ?的路徑。當編譯好腳本時,如果要執行該腳本,我們還必須使其可執行。要使腳本可執行,我們需賦予該文件可執行的權限,可以使用如下命令文件: chmod +x [文件] 或者 chmod 777 [文件]修改文件權限,之前也有講可參看:C語言再學習 -- 修改linux文件權限(2)注釋
在進行 shell 編程時,以“#”開頭的句子表示注釋,直到這一行的結束,我們建議在程序中使用注釋。使用注釋,即使相當長的時間內沒有使用該腳本,我們也能在很短的時間內明白該腳本的作用及工作原理。(3)提示符
在腳本中使用提示符“$”,后面使用圓括號括住命令,則可以執行該命令。 如果是環境變量,則直接跟在“$”后面。 實例: 查看腳本 # cat sh.sh #!/bin/bash echo $(ls) echo $SHELL執行腳本 # ./sh.sh sh.sh text.txt /bin/bash2、腳本演示
(1)創建腳本
#!/bin/bash #program date #show the date in this way echo "Mr.$USER,Today is:" #echo $(date) echo $(date) echo Wish you a lucky day !(2)設置可執行權限
# chmod 777 sh.sh(3)執行程序
# ./sh.sh Mr.root,Today is: Wed Mar 22 10:47:33 CST 2017 Wish you a lucky day !五、shell編程語法
shell 編程語法主要有變量、控制結構和函數三部分。 其中控制結構和函數,與C語言類似。 參看:C語言再學習 -- 分支與跳轉語句 參看:C語言再學習 -- 循環語句 參看:C語言再學習 -- 函數1、變量
與各種高級程序設計語言相似,shell 環境下我們也可以使用一組文字或符號,來替換一些設置或者一串保留的數據,這組文字或符號便是 shell 變量。根據使用功能不同我們將 shell 變量分為用戶自定義變量、位置參數與環境變量。(1)自定義變量
定義:變量名=變量值 在使用變量之前不需要事先聲明,我們只需要通過“=”,給它們賦初始值便可使用。注意,等號兩邊不能留空格,如果一定要出現空格,就要用雙引號括起來。 實例: # here=beijing此時系統便定義了 here 這個內容 為 beijing 的變量。查看變量內容我們可以在變量前面加上一個“$”符號,再用 echo 命令將其內容輸出到終端上。 # here=beijing # echo $here beijing 這部分類似于環境變量,在此不多講,參看:UNIX再學習 -- 環境變量(2)位置參數變量
在 Linux/UNIX 系統中,shell 腳本執行時是可以帶實參的。這些實參在腳本執行期間將會被賦予系統中自動定義好的一類變量中,這類變量就是位置參數變量。 命令行實參與腳本中位置參數變量的相對應關系如下所示: $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}$0:腳本名稱
$1-$9:第 1 至第 9 個參數
${}:獲取第 9 個以上參數
$#:表示傳給腳本或者函數的位置參數的個數(不包括“$0”)
$*:所有位置參數的列表,形式是一個單個字符串,串中第 1 個參數由第 1 個字符串分隔
$@:所有位置參數被分別表示為雙引號中的N(參數個數,不含$0)個字符串
$* 和?$@ 均可以表示所有位置參數,但它們之間卻存在著很大的不同,這種不同允許用兩種方式來處理命令行參數。 第一種:“$*”,因為它是一個單個字符,所以可以不需要很多 shell 代碼來顯示它,相比之下更加靈活。 第二種:“$@”,它允許我們獨立處理每個參數,因為它的值是 N 個分離參數。
再有,在執行 shell 程序時,位置參數變量并不是固定不變的,利用 set 命令可以為位置參數賦值或重新賦值。 實例: # echo 1 2 3 1 2 3分析:有 4 個位置參數 1 個命令名(echo) + 3 個參量 (1、2、3),$0 = ehco $1 = 1 $2 = 2 $3 = 3 #!/bin/bash echo "one=$1" echo "two=$2" echo "three=$3" echo "count=$#" echo "all=$*" echo "all=$@" set A B C echo "all=$*"執行腳本:# ./sh.sh 1 2 3 one=1 two=2 three=3 count=3 all=1 2 3 all=1 2 3 all=A B C
(3)環境變量
這部分不多講,參看:UNIX再學習 -- 環境變量2、控制結構
shell 程序設計語言的基礎是對條件進行測試判斷,根據不同的測試結果采取相應的程序處理。下面我們先分析在 shell 腳本程序中可以使用的判斷條件,然后講解使用這些條件的控制結構。(1)判斷條件
條件測試
條件測試有兩種常用形式:第一種是用 test 命令與系統運算符一起使用,第二種是用一對方括號與系統運算符一起使用。這兩種形式是完全等價的。注意,利用一對方括號表示條件測試時,左方括號“[”之后、右方括號“]”之前各應有一個空格。在大多數系統中,兩者沒有太大的區別,都使得程序設計語法看起來更加簡單明了。 實例:#!/bin/bash #if test -f "$1" if [ -f "$1" ] then echo "$1 is an ordinary file." else echo "$1 is not ordinary file." fi執行腳本:# ./sh.sh hello.txt hello.txt is not ordinary file.shell 編程中的 test 與 [] 命令 常見用法: 參看:test 命令 判斷表達式: if test #表達式為真 if test ! #表達式為假 test 表達式1 –a 表達式2 #兩個表達式都為真 test 表達式1 –o 表達式2 #兩個表達式有一個為真 test 表達式1 ! 表達式2 #條件求反判斷字符串: test –n 字符串 #字符串的長度非零 test –z 字符串 #字符串的長度是否為零 test 字符串1=字符串2 #字符串是否相等,若相等返回true test 字符串1!=字符串2 #字符串是否不等,若不等反悔false 判斷整數: test 整數1 -eq 整數2 #整數相等 test 整數1 -ge 整數2 #整數1大于等于整數2 test 整數1 -gt 整數2 #整數1大于整數2 test 整數1 -le 整數2 #整數1小于等于整數2 test 整數1 -lt 整數2 #整數1小于整數2 test 整數1 -ne 整數2 #整數1不等于整數2 判斷文件:test File1 –ef File2 兩個文件是否為同一個文件,可用于硬連接。主要判斷兩個文件是否指向同一個inode。 test File1 –nt File2 判斷文件1是否比文件2新 test File1 –ot File2 判斷文件1比是否文件2舊 test –b file #文件是否塊設備文件 test –c File #文件并且是字符設備文件 test –d File #文件并且是目錄 test –e File #文件是否存在 (常用) test –f File #文件是否為正規文件 (常用) test –g File #文件是否是設置了組id test –G File #文件屬于的有效組ID test –h File #文件是否是一個符號鏈接(同-L) test –k File #文件是否設置了Sticky bit位 test –b File #文件存在并且是塊設備文件 test –L File #文件是否是一個符號鏈接(同-h) test –o File #文件的屬于有效用戶ID test –p File #文件是一個命名管道 test –r File #文件是否可讀 test –s File #文件是否是非空白文件 test –t FD #文件描述符是在一個終端打開的 test –u File #文件存在并且設置了它的set-user-id位 test –w File #文件是否存在并可寫 test –x File #文件屬否存在并可執行
條件測試應用:
在實際 shell 程序設計中,使用單一判斷條件的情況很少,它往往與 &&、|| 等組成符合判斷條件來使用。 語法結構如下: 判斷條件1 && 判斷條件2 判斷條件3 || 判斷條件4 語法分析如下:? 判斷條件1 為真時才會執行 判斷條件2,否則忽略 判斷條件2 判斷條件3 為假時才會執行 判斷條件4,否則忽略 判斷條件4 #!/bin/bash if [ $1 -ge 0 ] && [ $1 -lt 10 ]; then echo "0 < $1 < 10" fi執行腳本:# ./sh.sh 3 0 < 3 < 10(2)條件判斷結構
if 語句
功能:用于條件控制結構中 語法格式1:if [條件判斷表達式]; then 當條件表達式成立時,可以執行命令 fi語法格式2: if [條件判斷表達式]; then 當條件表達式成立時,可以執行命令 else 當條件表達式不成立時,可以執行命令 fi語法格式3: if [條件判斷表達式1]; then 當條件表達式1成立時,可以執行命令 elfi [條件判斷表達式2]; then 當條件表達式2成立時,可以執行命令 else 當條件表達式1與2均不成立時,可執行命令 fi實例: #!/bin/bash #if test -f "$1" if [ -f "$1" ] then echo "$1 is an ordinary file." else echo "$1 is not ordinary file." fi執行腳本:# ./sh.sh hello.txt hello.txt is not ordinary file.case語句
功能:允許進行多重條件選擇語法結構:case $變量名稱 in 第一個變量內容) 程序段 (滿足第一個變量內容) ;; 第二個變量內容) 程序段二(滿足第二個變量內容) ;; ... *) 程序段(均不滿足前面的條件下) ... ;; esac語法分析:該語句執行過程是用“字符串”的值依次與各模式字符串進行比較,如果發現同某個匹配,那么就執行該模式字符串之后的各個命令,直至遇到兩個分號為止;如果沒有任何模式字符串與該字符串的值相符合,則不執行任何命令。在使用 case 語句時我們應該注意以下幾點:? ? 每個模式字符串后面可有一條或多條命令,它的最后一條命令必須以兩個分號(即;;)結束。? ? 模式字符串中可以使用通配符。? ? 如果一個模式字符串中包含多個模式,那么各模式之間應以豎線(|)隔開,表示各模式是“或”的關系,即只要給定字符串與其中一個模式相配,就會執行其后的命令表。? ? 各模式字符串應是唯一的,不應重復出現,因為“*”可以與任何字符串匹配,它如果第一個出現,就不會再檢查其他模式了。? ? case 語句以關鍵字 case 開頭,以關鍵字 esac (是 case 倒過來寫)結束。? ? case 的退出(返回)值是整個結構中最后執行的那個命令的退出值;如果沒有執行任何命令,那么退出值為零。 實例: #!/bin/bash echo "a) choice a" echo "b) choice b" echo "c) choice c" echo -e "Please enter your choice:\c" read menu_choice case "$menu_choice" in a) echo "you choice a" ;; b) echo "you choice b" ;; c) echo "you choice c" ;; *) echo "sorry, choice not exist" ;; esac執行腳本# ./sh.sh a) choice a b) choice b c) choice c Please enter your choice:a you choice a
(3)循環結構
循環可以不斷執行某個程序段,直到用戶設置的條件實現為止。下面介紹幾種常用的循環結構:while do done 語句
語法結構:while [條件判斷表達式] do 程序段 done語法分析: 當條件判斷表達式成立時,就進行循環,直到條件判斷表達式不成立才停止。 實例: #!/bin/bash echo "a) choice a" echo "b) choice b" echo "c) choice c" echo -e "Please enter your choice:\c" read menu_choice while [ "$menu_choice" != "a" ] && [ "$menu_choice" != "b" ] && [ "$menu_choice" != "c" ] do echo -e "Please enter your choice (a/b/c) to stop this programe:\c" read menu_choice done 執行腳本# ./sh.sh a) choice a b) choice b c) choice c Please enter your choice:d Please enter your choice (a/b/c) to stop this programe:auntil do done 語句
語法結構: until [條件判斷表達式] do 程序段 done語法分析: 與前面的 while do done 剛好相反,它說的是“當條件判斷表達式成立時,就終止循環,否則就持續執行循環的程序段” 實例: #!/bin/bash echo "a) choice a" echo "b) choice b" echo "c) choice c" echo -e "Please enter your choice:\c" read menu_choice until [ "$menu_choice" = "a" ] || [ "$menu_choice" = "b" ] || [ "$menu_choice" = "c" ] do echo -e "Please enter your choice (a/b/c) to stop this programe:\c" read menu_choice done執行腳本:# ./sh.sh a) choice a b) choice b c) choice c Please enter your choice:d Please enter your choice (a/b/c) to stop this programe:afor do done 語句
語句結構: for [條件判斷表達式] do 程序段 done語法分析: for 語句是最常用的建立循環結構的語句,其條件判斷表達式更是形式多樣,同 while 一樣,是當滿足條件判斷時,就進行循環,知道條件不成立才停止。 實例:#!/bin/bash for num in 1 2 3 4 5 do echo "$num" done執行腳本:# ./sh.sh 1 2 3 4 5(4)其他結構:break 命令 和 continue 命令
break 命令
功能:可以使我們從循環體重退出來 語法格式:break [ n ] 命令中 n 表示要跳出幾層循環,默認值是 1,表示只跳出一層循環continue 命令
功能:跳出循環體在它之后的語句,回到本層循環的開頭,進行下次循環。 語法格式: continue [ n ] 命令中 n 表示從包含 continue 語句的最內層循環體向外跳到第幾層循環,默認值為 1,循環層數由內向外編號。3、函數
到目前為止所編寫的 shell 程序都是非常短小的。在實際應用中,有時為項目所編寫的腳本程序時非常大型的,這時我們該如何構造自己的代碼呢?可能想到說講大型腳本按照功能模塊拆分成多個小型腳本,但這種做法存在如下幾個缺點. ? ? 在一個腳本程序中運行另外一個腳本程序要比執行一個函數慢得多。 ? ? 返回執行結果變得更加困難,而且可能存在非常多的小腳本。 基于上面原因及拆分思想,我們可以定義并使用 shell 函數 語法格式: [function]函數名() {命令表 (statements) }語法分析: 關鍵字 function 可以默認。通常,函數中的最后一個命令執行之后,就退出被調用函數。 我們也可以利用 return 命令立即退出函數 語法格式: return [ n ] 命令中,n 值是退出函數時的退出值(退出狀態),即 $? 的值。當 n 值缺省時,退出值是最后一個命令執行結果。函數應先定義,后使用。調用函數時,我們可以直接利用函數名,如 foo 不必帶圓括號,就像一般命令那樣使用。使用函數的最大作用就是可以簡化很多代碼,這在較大的 shell 腳本設計中國可能會更加明顯。實例: #!/bin/bash first () {echo "*****************************" } second () {echo "=============================" } trird () {echo -e "\fhello world!\f" } first second trird second first執行腳本:# ./sh.sh ***************************** =============================hello world!============================= *****************************
六、實例展示
#!/bin/sh e="" m="" n="xxxx" while [ 1 ] don="xxxx"e=`fdisk -l | grep /dev/sdb1 | awk '{print $1}'`if [ -z "$e" ];thenecho "####no sd ####"elseecho "####have sd !####"m=`df | grep media | awk '{print $1}'`if [ -n "$m" ];thenumount $mfi#umount $eecho "####start to format sd with ext3 filesystem!####"mkfs.ext3 "$e"echo "####end format sd!####"#echo "copy zslf_app_dir"mount $e /media/mmcblk0p1mkdir /media/mmcblk0p1/bakmkdir /media/mmcblk0p1/videomkdir /media/mmcblk0p1/video/tempumount $eecho "please remove sd!"fisleep 5if [ -n "$e" ];thenwhile [ -n "$n" ]don=`fdisk -l | grep /dev/sdb1 | awk '{print $1}'`sleep 5donefi done #!/bin/sh php_config_copy () {echo "start copy the config file from jyzc to thttpd/www."cp /jyzc/config/encodeCfg.xml /jyzc/thttpd-php/www/config/encodeCfg.xmlcp /jyzc/config/devInfo.txt /jyzc/thttpd-php/www/config/devInfo.txtcp /etc/network/interfaces /jyzc/thttpd-php/www/config/interfaces } ppp_config_copy {echo "start copy th config file from jyzc/config to /etc/ppp/peers."cp /jyzc/config/ppp-off /etc/ppp/peers/cp /jyzc/config/ppp0_on_state.txt /etc/ppp/peers/ } echo "############## jyzc ##################" php_config_copy ppp_config_copy route del default mknod /dev/pio c 203 0 cd /etc/ppp/information/ rm -rf addr.txt echo " " > /etc/ppp/information/state.txt#mknod -m 660 /dev/ttyUSB0 c 188 0 #mknod -m 660 /dev/ttyUSB1 c 188 1 #mknod -m 660 /dev/ttyUSB2 c 188 2 #mknod -m 660 /dev/ttyUSB3 c 188 3 #mknod -m 660 /dev/ttyUSB4 c 188 4 #mknod -m 660 /dev/ttyUSB5 c 188 5/jyzc/ntpdate_first.sh & ./state.sh & /jyzc/create_mem & sleep 5 #/jyzc/3gStrength & /jyzc/thttpd-php/sbin/thttpd -C /jyzc/thttpd-php/thttpd.conf sleep 1 vsftpd sleep 2 mkdir /media/mmcblk0p1/bak cd /jyzc/config/ ./srv 8000 & ./pio_led & /jyzc/rm_pic.sh G LTE Setup Script #/jyzc/LteSetUp.sh & #sleep 10 #i=`cat /proc/bus/usb/devices | grep ProdID=1573` #./MU609-3gState & insmod /jyzc/usbnet.ko insmod /jyzc/cdc_encap.ko insmod /jyzc/cdc_ether.ko sleep 2 /jyzc/ME3760Connectecho "######## encode #########" cd /jyzc ./initial.sh ./get_ntptime & ./encode & ./thttpd.sh &總結
以上是生活随笔為你收集整理的UNIX再学习 -- shell编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringCloud Feign实战(
- 下一篇: UNIX再学习 -- 文件描述符