linux Shell(脚本)编程入门实例讲解详解
linux Shell(腳本)編程入門實例講解詳解
為什么要進行shell編程
在Linux系統中,雖然有各種各樣的圖形化接口工具,但是sell仍然是一個非常靈活的工具。Shell不僅僅是命令的收集,而且是一門非常棒的編程語言。您可以通過使用shell使大量的任務自動化,shell特別擅長系統管理任務,尤其適合那些易用性、可維護性和便攜性比效率更重要的任務。
下面,讓我們一起來看看shell是如何工作的:
建立一個腳本
Linux中有好多中不同的shell,但是通常我們使用bash (bourne again shell)?進行shell編程,因為bash是免費的并且很容易使用。所以在本文中筆者所提供的腳本都是使用bash(但是在大多數情況下,這些腳本同樣可以在bash的大姐,bourne shell中運行)。
如同其他語言一樣,通過我們使用任意一種文字編輯器,比如nedit、kedit、emacs、vi等來編寫我們的shell程序。程序必須以下面的行開始(必須方在文件的第一行):
| #!/bin/sh |
符號#!用來告訴系統它后面的參數是用來執行該文件的程序。在這個例子中我們使用/bin/sh來執行程序。當編輯好腳本時,如果要執行該腳本,還必須使其可執行。
要使腳本可執行:
| chmod +x filename |
然后,您可以通過輸入:?./filename?來執行您的腳本。
注釋
在進行shell編程時,以#開頭的句子表示注釋,直到這一行的結束。我們真誠地建議您在程序中使用注釋。如果您使用了注釋,那么即使相當長的時間內沒有使用該腳本,您也能在很短的時間內明白該腳本的作用及工作原理。
變量
在其他編程語言中您必須使用變量。在shell編程中,所有的變量都由字符串組成,并且您不需要對變量進行聲明。要賦值給一個變量,您可以這樣寫:
變量名=值
取出變量值可以加一個美元符號($)在變量前面:
| #!/bin/sh |
#對變量賦值:
| a="hello world" |
#?現在打印變量a的內容:
| echo "A is:" echo $a |
在您的編輯器中輸入以上內容,然后將其保存為一個文件first。之后執行chmod +x first。使其可執行,最后輸入./first執行該腳本。
這個腳本將會輸出:
| A is: hello world |
有時候變量名很容易與其他文字混淆,比如:
| num=2 echo "this is the $numnd" |
這并不會打印出"this is the 2nd",而僅僅打印"this is the ",因為shell會去搜索變量numnd的值,但是這個變量時沒有值的??梢允褂没ɡㄌ杹砀嬖Vshell我們要打印的是num變量:
| num=2 echo "this is the $nd" |
這將打印:?this is the 2nd
有許多變量是系統自動設定的,這將在后面使用這些變量時進行討論。
如果您需要處理數學表達式,那么您需要使用諸如expr等程序(見下面)。除了一般的僅在程序內有效的shell變量以外,還有環境變量。由export關鍵字處理過的變量叫做環境變量。我們不對環境變量進行討論,因為通常情況下僅僅在登錄腳本中使用環境變量。
Shell命令和流程控制
在shell腳本中可以使用三類命令:
1)Unix?命令:
雖然在shell腳本中可以使用任意的unix命令,但是還是由一些相對更常用的命令。這些命令通常是用來進行文件和文字操作的。
常用命令語法及功能:
echo "some text":?將文字內容打印在屏幕上。
ls:?文件列表。
wc –l file wc -w file wc -c file:?計算文件行數 計算文件中的單詞數 計算文件中的字符數。
cp sourcefile destfile:?文件拷貝。
mv oldname newname :?重命名文件或移動文件。
rm file:?刪除文件。
grep 'pattern' file:?在文件內搜索字符串比如:grep 'searchstring' file.txt
cut -b colnum file:?指定欲顯示的文件內容范圍,并將它們輸出到標準輸出設備比如:輸出每行第5個到第9個字符cut –b 5-9 file.txt千萬不要和cat命令混淆,這是兩個完全不同的命令。
cat file.txt:?輸出文件內容到標準輸出設備(屏幕)上。
file somefile:?得到文件類型。
read var:?提示用戶輸入,并將輸入賦值給變量。
sort file.txt:?對file.txt文件中的行進行排序。
uniq:?刪除文本文件中出現的行列比如:?sort file.txt | uniq。
expr:?進行數學運算Example: add 2 and 3 expr 2 "+" 3。
find:?搜索文件比如:根據文件名搜索find . -name filename -print。
tee:?將數據輸出到標準輸出設備(屏幕)?和文件比如:somecommand | tee outfile。
basename file:?返回不包含路徑的文件名比如:?basename /bin/tux將返回?tux。
dirname file:?返回文件所在路徑比如:dirname /bin/tux將返回?/bin。
head file:?打印文本文件開頭幾行。
tail file :?打印文本文件末尾幾行。
sed: Sed是一個基本的查找替換程序??梢詮臉藴瘦斎?#xff08;比如命令管道)讀入文本,并將結果輸出到標準輸出(屏幕)。該命令采用正則表達式(見參考)進行搜索。不要和shell中的通配符相混淆。比如:將linuxfocus?替換為?LinuxFocus?:cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file。
awk: awk?用來從文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。cat file.txt | awk -F, '{print "," }'這里我們使用,作為字段分割符,同時打印第一個和第三個字段。如果該文件內容如下:
| Adam Bor, 34, IndiaKerry Miller, 22,?USA |
命令輸出結果為:
| Adam Bor, IndiaKerry Miller. |
2)?概念:?管道,?重定向和?backtick
這些不是系統命令,但是他們真的很重要。
管道?(|)?將一個命令的輸出作為另外一個命令的輸入。
| grep "hello" file.txt | wc -l |
在file.txt中搜索包含有”hello”的行并計算其行數。在這里grep命令的輸出作為wc命令的輸入。當然您可以使用多個命令。
重定向:將命令的結果輸出到文件,而不是標準輸出(屏幕)。
>?寫入文件并覆蓋舊文件。
>>?加到文件的尾部,保留舊文件內容。
反短斜線,使用反短斜線可以將一個命令的輸出作為另外一個命令的一個命令行參數。
命令:
| find . -mtime -1 -type f -print |
用來查找過去24小時(-mtime –2則表示過去48小時)內修改過的文件。如果您想將所有查找到的文件打一個包,則可以使用以下腳本:
| #!/bin/sh # The ticks are backticks (`) not normal quotes ('): tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print` |
3)?流程控制
"if"?表達式 如果條件為真則執行then后面的部分:
if ....; then
?
==========================================================================
shell腳本實例
#! /bin/sh
echo "Current command is $0"
echo "The first parameter is $1"
echo "The second parameter is $2"
echo "The third parameter is $3"
echo "Total of parameters if $#"
echo "Current PID is $$"
#!/bin/bash
times=0
until [ "$times" = 3 ];
do
??echo "I love linux."
??sleep 2
??times=`expr $times + 1`
done
??
#!/bin/bash
# menu shell script.? ?? ?samli? ???2004.4.19
until?
? ?? ? echo "List Directory..........1"?
? ?? ? echo "Change Directory........2"?
? ?? ? echo "Edit File...............3"?
? ?? ? echo "Remove File.............4"?
? ?? ? echo "Exit Menu...............5"?
? ?? ? read choice?
? ?? ? test $choice = 5
do?
? ?? ? case $choice in?
? ?? ?? ?? ???1) ls;;?
? ?? ?? ?? ???2) echo "enter target directory:"?
? ?? ?? ?? ???read dir?
? ?? ?? ?? ???cd $dir?
? ?? ?? ?? ???;;?
? ?? ?? ?? ???3) echo "enter file name:"?
? ?? ?? ?? ???read file?
? ?? ?? ?? ???vi $file?
? ?? ?? ?? ???;;?
? ?? ?? ?? ???4) echo "enter file name:"?
? ?? ?? ?? ???read file?
? ?? ?? ?? ???rm $file?
? ?? ?? ?? ???;;?
? ?? ?? ?? ???5) echo "Goodbye"
? ?? ?? ?? ???;;?
? ?? ?? ?? ???*) echo "illegal option, please input again."?
? ?? ? esac?
done?
#! /bin/sh
var1="abcd??efg"
echo $var1
var2=1234
echo "The value of var2 is $var2"
echo??$HOME
echo??$PATH
echo??$PWD
#! /bin/sh
num=0
while [ $num -le 10 ]
do
? ? num=`expr $num + 1`
? ?? ? if [ $num -eq 5 ]
? ?? ? then
? ?? ?? ?? ???continue??
? ?? ? fi
? ? square=`expr $num \* $num`
? ? echo $square
done
#!/bin/bash?
# Gnu bash versions 2.x
# The Party Program--Invitations to friends from the?
# "guest" file?
guestfile=./guests??#??~/shell/guests
if [[ ! -e "$guestfile" ]]?
then
? ?? ? printf "${guestfile##*/} non-existent"
? ?? ? exit 1
fi
export PLACE="Sarotini's"
(( Time=$(date +%H) + 1 ))
set cheese crackers shrimp drinks "hot dogs" sandwiches?
for person in $(cat $guestfile)?
do
? ?? ? if??[[ $person = root ]]
? ?? ? then
? ?? ?? ?? ???continue
? ?? ? else?
? ?? ?? ?? ???# Start of here document
? ?? ?? ?? ???mail -v -s "Party" $person?
? ?? ?? ?? ???Hi ${person}! Please join me at $PLACE for a party!?
? ?? ?? ?? ???Meet me at $Time o'clock.
? ?? ?? ?? ???I'll bring the ice cream. Would you please bring $1?
? ?? ?? ?? ???and anything else you would like to eat? Let me know?
? ?? ?? ?? ???if you can't make it.
? ?? ?? ?? ?? ?? ?? ?Hope to see you soon.
? ?? ?? ?? ?? ?? ?? ?? ?? ?Your pal,
? ?? ?? ?? ?? ?? ?? ?? ?? ?ellie@$(hostname)
? ?? ?? ?? ???FINIS
? ?? ?? ?? ???shift?
? ?? ?? ?? ???if (( $# ==??0 ))?
? ?? ?? ?? ???then
? ?? ?? ?? ?? ?? ?? ?set cheese crackers shrimp drinks "hot dogs" sandwiches
? ?? ?? ?? ???fi
? ?? ???fi
done? ?? ?? ?? ???
printf "Bye..."?
#!/bin/sh?
# Standard AT&T Bourne Shell?
# The Party Program--Invitations to friends from the?
# "guest" file?
guestfile=./guests? ?# /home/ellie/shell/guests
if [ ! -f "$guestfile" ]?
then
? ?? ? echo "慴asename $guestfile?non-existent"
? ?? ? exit 1
fi
PLACE="Sarotini's"
export PLACE
Time=`date +%H`
Time=`expr $Time + 1`
set cheese crackers shrimp drinks "hot dogs" sandwiches?
for person in $(cat $guestfile)?
do
? ?? ? if??[ $person = root ]]
? ?? ? then
? ?? ?? ?? ???continue
? ?? ? else?
? ?? ?? ?? ???# Start of here document
? ?? ?? ?? ???mail -v -s "Party" $person?
? ?? ?? ?? ???Hi $person! Please join me at $PLACE for a party!?
? ?? ?? ?? ???Meet me at $Time o'clock.
? ?? ?? ?? ???I'll bring the ice cream. Would you please bring $1?
? ?? ?? ?? ???and anything else you would like to eat? Let me know?
? ?? ?? ?? ???if you can't? ?? ?? ?? ?? ?? ?? ?? ?? ?? ???make it.
? ?? ?? ?? ?? ?? ?? ?Hope to see you soon.
? ?? ?? ?? ?? ?? ?? ?? ?? ?Your pal,
? ?? ?? ?? ?? ?? ?? ?? ?? ?ellie@`hostname`
? ?? ?? ?? ???FINIS
? ?? ?? ?? ???shift?
? ?? ?? ?? ???if [ $# -eq??0 ]?
? ?? ?? ?? ???then
? ?? ?? ?? ?? ?? ?? ?set cheese crackers shrimp drinks "hot dogs" sandwiches
? ?? ?? ?? ???fi
? ?? ???fi
done? ?? ?? ?? ???
echo "Bye..."?
#!/bin/sh
# Scriptname: args
# Script to test command line arguments
echo The name of this script is $0.
echo The arguments are $*.
echo The first argument is $1.
echo The second argument is $2.
echo The number of arguments is $#.
oldargs=$*
set Jake Nicky Scott? ?? ?? ?? ?? ?? ???# reset the positional parameters
echo All the positional parameters are $*.
echo The number of postional parameters is $#.
echo "Good~Vbye for now, $1 "
set $(date)? ?? ?? ?? ?? ?? ?? ???#??reset the positional parameters
echo The date is $2 $3, $6.
echo "The value of \$oldargs is $oldargs."
set $oldargs
echo $1 $2 $3
# Name: bigfiles
# Purpose: Use the find command to find any files in the root
# partition that have not been modified within the past n (any
# number within 30 days) days and are larger than 20 blocks
# (512 byte blocks)
if (( $# != 2 ))? ?#??or? ???[ $# -ne 2 ]
then
? ?echo??"Usage:? ?$0 mdays size " 1>&2
? ?exit 1
fi
if (( $1? ?0 || $1 > 30 )) #??or??[ $1 -lt 0 -o $1 -gt 30 ]
then
? ?echo "mdays is out of range"
? ?exit 2
fi
if (( $2? ? #? ?or??[ $2 -le 20 ]
then
? ?echo "size is out of range"
? ?exit 3
fi
find / -xdev -mtime $1 -size +$2
#!/bin/bash
# Scriptname: checker
# Script to demonstrate the use of special variable
# modifiers and arguments
name=${1:?"requires an argument" }
echo Hello $name
#!/bin/bash
# This is the first Bash shell program of the day.
# Scriptname: greetings
# Written by:??Barbara Bashful
echo "Hello $LOGNAME, it's nice talking to you."
echo "Your present working directory is `pwd`."
echo "You are working on a machine called `uname -n`."
echo "Here is a list of your files."
ls? ?? ?# list files in the present working directory
echo??"Bye for now $LOGNAME. The time is `date +%T`!"
#!/bin/bash
# Scriptname: greetings2
echo "This script is called $0."
echo??"$0??$1 and $2"
echo "The number of positional parameters is $#"
#!/bin/bash
# Scriptname: idcheck
# purpose:check user id to see if user is root.
# Only root has a uid of 0.
# Format for id output:uid=9496(ellie) gid=40 groups=40
# root's uid=0
id=`id | gawk -F'[=(]'??'{print $2}'`? ???# get user id
echo your user id is:??$id
if??(( id == 0 ))? ? # or? ?[ $id -eq 0 ]
then
? ?echo "you are superuser."
else
? ?echo "you are not superuser."
fi
================================================================================================
第12章?Shell腳本編程
| |
- Shell命令行的運行
- 編寫、修改權限和執行Shell程序的步驟
- 在Shell程序中使用參數和變量
- 表達式比較、循環結構語句和條件結構語句
- 在Shell程序中使用函數和調用其他Shell程序
12-1???Shell命令行書寫規則
- Shell命令行的書寫規則
對Shell命令行基本功能的理解有助于編寫更好的Shell程序,在執行Shell命令時多個命令可以在一個命令行上運行,但此時要使用分號(;)分隔命令,例如:
[root@localhost??root]# ls a* -l;free;df
長Shell命令行可以使用反斜線字符(\)在命令行上擴充,例如:
[root@localhost??root]# echo “this is \
>long command”
This is long command
?注意:
“>”符號是自動產生的,而不是輸入的。
????????????12-2??編寫/修改權限及執行Shell程序的步驟
- 編寫Shell程序
- 執行Shell程序
Shell程序有很多類似C語言和其他程序設計語言的特征,但是又沒有程序語言那樣復雜。Shell程序是指放在一個文件中的一系列Linux命令和實用程序。在執行的時候,通過Linux操作系統一個接一個地解釋和執行每條命令。首先,來編寫第一個Shell程序,從中學習Shell程序的編寫、修改權限、執行過程。
12-2-1??編輯Shell程序
編輯一個內容如下的源程序,保存文件名為date,可將其存放在目錄/bin下。
[root@localhost??bin]#vi date
#! /bin/sh
echo “Mr.$USER,Today is:”
echo &date “+%B%d%A”
echo “Wish you a lucky day !”
?注意:
#! /bin/sh通知采用Bash解釋。如果在echo語句中執行Shell命令date,則需要在date命令前加符號“&”,其中%B%d%A為輸入格式控制符。
12-2-2建立可執行程序
????編輯完該文件之后不能立即執行該文件,需給文件設置可執行程序權限。使用如下命令。
[root@localhost??bin]#chmod +x date
12-2-3??執行Shell程序
執行Shell程序有下面三種方法:
方法一:
[root@localhost??bin]#./ date
Mr.root,Today is:
二月?06?星期二
Wish you a lucky day !
方法二:
另一種執行date的方法就是把它作為一個參數傳遞給Shell命令:
[root@localhost??bin]# Bash date
Mr.root,Today is:
二月?06?星期二
Wish you a lucky day !
方法三:
?為了在任何目錄都可以編譯和執行Shell所編寫的程序,即把/bin的這個目錄添加到整個環境變量中。
具體操作如下:
[root@localhost??root]#export PATH=/bin:$PATH
[root@localhost??bin]# date
Mr.root,Today is:
二月?06?星期二
Wish you a lucky day !
實例?12-1:編寫一個Shell程序mkf,此程序的功能是:顯示root下的文件信息,然后建立一個kk的文件夾,在此文件夾下建立一個文件aa,修改此文件的權限為可執行。
分析:此Shell程序中需要依次執行下列命令為:
進入root目錄:cd /root
顯示root目錄下的文件信息:ls –l
新建文件夾kk: mkdir kk
進入root/kk目錄:cd kk
新建一個文件aa:??vi aa??#編輯完成后需手工保存
修改aa文件的權限為可執行:chmod +x aa
回到root目錄:cd /root
因此該Shell程序只是以上命令的順序集合,假定程序名為mkf
[root@localhost??root]#vi mkf
cd /root
ls –l
mkdir kk
cd kk
vi aa
chmod +x aa
cd /root
????????????????????12-3??在Shell程序中使用的參數
- 位置參數
- 內部參數
如同ls命令可以接受目錄等作為它的參數一樣,在Shell編程時同樣可以使用參數。Shell程序中的參數分為位置參數和內部參數等。
12-3-1??位置參數
由系統提供的參數稱為位置參數。位置參數的值可以用$N得到,N是一個數字,如果為1,即$1。類似C語言中的數組,Linux會把輸入的命令字符串分段并給每段進行標號,標號從0開始。第0號為程序名字,從1開始就表示傳遞給程序的參數。如$0表示程序的名字,$1表示傳遞給程序的第一個參數,以此類推。
12-3-2??內部參數
上述過程中的$0是一個內部變量,它是必須的,而$1則可有可無,最常用的內部變量有$0、$#、$?、$*,它們的含義如下。
- $0:命令含命令所在的路徑。
- $#:傳遞給程序的總的參數數目。
- $?:Shell程序在Shell中退出的情況,正常退出返回0,反之為非0值。
- $*:傳遞給程序的所有參數組成的字符串。
實例?12-2:編寫一個Shell程序,用于描述Shell程序中的位置參數為:$0、$#、$?、$*,程序名為test1,代碼如下:
[root@localhost??bin]#vi test1
#! /bin/sh
echo “Program name is $0”;
echo “There are totally $# parameters passed to this program”;
echo “The last is $?”;
echo “The parameter are $*”;
執行后的結果如下:
[root@localhost??bin]# test1 this is a test program??//傳遞5個參數
Program name is /bin/test1???????????????????????//給出程序的完整路徑和名字
There are totally 5 parameters passed to this program??//參數的總數
The last is 0????????????????????????????????????//程序執行效果
The parameters are this is a test program???????????//返回由參數組成的字符串
?
注意:命令不計算在參數內。
實例?12-3:利用內部變量和位置參數編寫一個名為test2的簡單刪除程序,如刪除的文件名為a,則在終端中輸入的命令為:test a
分析:除命令外至少還有一個位置參數,即$#不能為0,刪除不能為$1,程序設計過程如下。
[root@localhost??bin]#vi test2
#! /bin/sh
if test $# -eq 0
then
echo “Please specify a file!”
else
?gzip $1?????????????????????????//現對文件進行壓縮
mv $1.gz $HOME/dustbin???????????//移動到回收站
echo “File $1 is deleted !”????????????
fi
[root@localhost??bin]#chmod +x test2
(3)??運行
[root@localhost??bin]# test2 a?(如果a文件在bin目錄下存在)
File a is deleted!
????????????????12-4??在Shell程序中的使用變量
- 變量的賦值
- 變量的訪問
- 變量的輸入
?
12-4-1變量的賦值
???在Shell編程中,所有的變量名都由字符串組成,并且不需要對變量進行聲明。要賦值給一個變量,其格式如下:
變量名=值
?注意:
等號(=)前后沒有空格
例如:
???x=6
???a=”How are you ”
表示把6賦值給變量x,字符串“How are you?”賦值給變量a。
12-4-2??訪問變量值
如果要訪問變量值,可以在變量前面加一個美元符號“$”,例如:
?[root@localhost??bin]#a=”How are you ”
?[root@localhost??bin]#echo “He juest said:$a”
????A is:hello world
一個變量給另一個變量賦值可以寫成:
變量2=$變量1
例如:
x=$i
i++可以寫成:
i=$i+1
12-4-3鍵盤讀入變量值
???在Shell程序設計中,變量的值可以作為字符串從鍵盤讀入,其格式為:
?????read?變量
例如:
[root@localhost??bin]#read str
read為讀入命令,它表示從鍵盤讀入字符串到str。
實例?12-4:編寫一個Shell程序test3,程序執行時從鍵盤讀入一個目錄名,然后顯示這個目錄下所有文件的信息。
分析:
?存放目錄的變量為DIRECTORY,其讀入語句為:
read DIRECTORY
顯示文件的信息命令為:ls –a
?[root@localhost??bin]#vi test3
#! /bin/sh
echo “please input name of directory”
read DIRECTORY
cd $DIRECTORY
ls –l
(2)設置權限
[root@localhost??bin]#chmod +x test3
(3)執行
[root@localhost??bin]#./test3
?注意:
輸入路徑時需“/”
實例?12-5:運行程序test4,從鍵盤讀入x、y的值,然后做加法運算,最后輸出結果。
(1)用vi編輯程序
[root@localhost??bin]#vi test4
?#! /bin/sh
echo “please input x y”
read x,y
z=`expr $x+$y`
echo “The sum is $z”
(2)設置權限
[root@localhost??bin]#chmod +x test4
(3)執行
[root@localhost??bin]#./ test4
45 78
The sum is 123
?注意:
表達式total=`expr $total +$num`及num=`expr $num +1`中的符號“`”為鍵盤左上角的“`”鍵。
?
??????????????????????????12-5??表達式的比較
- 字符串操作符
- 邏輯運算符
- 用test比較的運算符
- 數字比較符
- 文件操作符
?
在Shell程序中,通常使用表達式比較來完成邏輯任務。表達式所代表的操作符有字符操作符、數字操作符、邏輯操作符、以及文件操作符。其中文件操作符是一種Shell所獨特的操作符。因為Shell里的變量都是字符串,為了達到對文件進行操作的目的,于是才提供了文件操作符。
12-5-1字符串比較
???作用:測試字符串是否相等、長度是否為零,字符串是否為NULL。
???常用的字符串操作符如表12-1所示.。
?????????????????????????表12-1???常用的字符串操作符
| ???????字符串操作符 | ??????????含義及返回值 |
| = | 比較兩個字符串是否相同,相同則為“真” |
| != | 比較兩個字符串是否不相同,不同則為“真” |
| -n | 比較兩個字符串長度是否大于零,若大于零則為“真” |
| -z | 比較兩個字符串長度是否等于零,若等于零則為“真” |
實例?12-6:從鍵盤輸入兩個字符串,判斷這兩個字符串是否相等,如相等輸出。
(1)用vi編輯程序
[root@localhost??bin]#vi test5
??#! /bin/Bash
read ar1
read ar2
[ “$ar1”?= “$ar2”?]
echo $? #?保存前一個命令的返回碼
(2)設置權限
[root@localhost??bin]#chmod +x test5
(3)執行
[root@localhost??root]#./ test5
aaa
bbb
1
?注意:
”[”后面和”]”前面及等號“=“的前后都應有一個空格;注意這里是程序的退出情況,如果ar1和ar2的字符串是不想等的非正常退出,輸出結果為1。
實例?12-7: 比較字符串長度是否大于零
(1)用vi編輯程序
[root@localhost??bin]#vi test6
#! /bin/Bash
read ar
?[??-n “$ar” ]
echo $????//保存前一個命令的返回碼
(2)設置權限
[root@localhost??bin]#chmod +x test6
(3)執行
[root@localhost??bin]#./ test6
0
?注意:
運行結果1表示ar的小于等于零,0表示ar的長度大于零。
12-5-2數字比較
???在Bash Shell編程中的關系運算有別于其他編程語言,用表12-2中的運算符用test語句表示大小的比較。
?????????????????????????表12-2??用test比較的運算符
| ??運算符號 | ??????????含????????????義 |
| -eq | ???????????相等 |
| ??????-ge | ?????????大于等于 |
| ??????-le | ?????????小于等于 |
| ??????-ne | ?????????不等于 |
| ??????-gt | ?????????大于 |
| ??????-lt | ?????????小于 |
實例?12-8:比較兩個數字是否相等
(1)用vi編輯程序
[root@localhost??bin]#vi test7
??#! /bin/Bash
read x,y
if test $x –eq $y
???then
?????echo “$x=$y”
else
?????echo “$x!=$y”
fi
(2)設置權限
[root@localhost??bin]#chmod +x test7
(3)執行
[root@localhost??bin]#./ test7
50 100
50!=100
[root@localhost??bin]#./ test7
??150 150
??150= =150
12-5-3邏輯操作
????在Shell程序設計中的邏輯運算符如表12-3所示。
??????????????????????12-3??Shell中的邏輯運算符
| 運算符號 | ??????????含????????????義 |
| ???! | 反:與一個邏輯值相反的邏輯值 |
| ???-a | 與(and):兩個邏輯值為“是”返回值為“是”,反之為“否” |
| ???-o | 或(or):?兩個邏輯值有一個為“是”,返回值就是“是” |
實例?12-9:分別給兩個字符變量賦值,一個變量賦予一定的值,另一個變量為空,求兩者的與、或操作。
(1)用vi編輯程序
[root@localhost??bin]#vi test8
??#! /bin/Bash
??part1 =”1111”
??part2 =” ”?????#part2為空
??[ “$ part1”?–a “$ part2”]
??echo $????????#保存前一個命令的返回碼
??[ “$ part1”?–o “$ part2”]
??echo $??????
(2)設置權限
[root@localhost??bin]#chmod +x test8
(3)執行
[root@localhost??bin]#./ test8
1
0
12-5-4文件操作
文件測試操作表達式通常是為了測試文件的信息,一般由腳本來決定文件是否應該備份、復制或刪除。由于test關于文件的操作符有很多,在表12-4中只列舉一些常用的操作符。
???????????????????????表12-4???文件測試操作符
| ???運算符號 | ??????????含????????????義 |
| -d | 對象存在且為目錄返回值為“是” |
| -f | 對象存在且為文件返回值為“是” |
| -L | 對象存在且為符號連接返回值為“是” |
| -r | 對象存在且可讀則返回值為“是” |
| -s | 對象存在且長度非零則返回值為“是” |
| -w | 對象存在且且可寫則返回值為“是” |
| -x | 對象存在且且可執行則返回值為“是” |
實例?12-10:判斷zb目錄是否存在于/root下。
(1)用vi編輯程序
[root@localhost??bin]#vi test9
#! /bin/Bash
[ -d /root/zb ]
echo $?????#保存前一個命令的返回碼
(2)設置權限
[root@localhost??bin]#chmod +x test9
??????(3)執行
[root@localhost??bint]#./ test9
??????(4)在/root添加zb目錄
??[root@localhost??bin]#mkdir zb
(5)執行
??[root@localhost??bin]#./test9
0
?注意:
運行結果是返回參數“$?”,結果1表示判斷的目錄不存在,0表示判斷的目錄不存在。
實例?12-11:編寫一個Shell程序test10,輸入一個字符串,如果是目錄,則顯示目錄下的信息,如為文件顯示文件的內容。
(1)用vi編輯程序
[root@localhost??bin]#vi test10
#! /bin/Bash
??echo “Please enter the directory name or file name”
??read DORF
??if [ -d $DORF ]
??then
ls $DORF
??elif [ -f $DORF ]
then
cat $DORF
else
??echo “input error! ”
fi
(2)設置權限
[root@localhost??bin]#chmod +x test10
(3)執行
[root@localhost??bin]#./ test10
?????????????????????????????12-6??循環結構語句
- Shell的循環語句
Shell常見的循環語句有for循環、while循環語句和until循環。
12-6-1??for循環
語法:
for?變量?in?列表
??do
????操作
??done
?注意:
變量要在循環內部用來指列表當中的對象。
列表是在for循環的內部要操作的對象,可以是字符串也可以是文件,如果是文件則為文件名。
實例?12-12:在列表中的值:a,b,c,e,I,2,4,6,8用循環的方式把字符與數字分成兩行輸出。
(1)用gedit編輯腳本程序test11
[root@localhost??bin]#gedit test11
#! /bin/Bash
for i in a,b,c,e,I??2,4,6,8
do
echo $i
done
(2)設置權限
[root@localhost??bin]#chmod +x test11
?(3)執行
[root@localhost??bin]#./ test11
a,b,c,e,i
2,4,6,8
?注意:
在循環列表中的空格可表示換行。
實例?12-13:刪除垃圾箱中的所有文件。
?????分析:在本機中,垃圾箱的位置是在$HOME/.Trash中,因而是在刪除$HOME/.Trash列表當中的所有文件,程序腳本如下。
(1)用gedit編輯腳本程序test12
[root@localhost??bin]#gedit test12
#! /bin/Bash
for i in $HOME/.Trash/*
do
????rm $ i
echo “$ i has been deleted!”
done
(2)設置權限
[root@localhost??bin]#chmod +x test12
(3)執行
[root@localhost??bin]#./ test12
/root/.Trash/abc~ has been deleted!
/root/.Trash/abc1 has been deleted!
實例?12-14:求從1~100的和。
?(1)用gedit編輯腳本程序test13
[root@localhost??bin]#gedit test13
#! /bin/Bash
total =0
for((j=1;j<=100;j++));
do
?????total=`expr $total + $j`
done
echo “The result is $total”
(2)設置權限
[root@localhost??bin]#chmod +x test13
(3)執行
[root@localhost??bin]#./ test13
The result is 5050
?注意:
for語句中的雙括號不能省,最后的分號可有可無,表達式total=`expr $total + $j`的加號兩邊的空格不能省,否則會成為字符串的連接。
12-6-2?while循環
???語法:
???while?表達式
?????do
???????操作
?????done
只要表達式為真,do和done之間的操作就一直會進行。
實例?12-15:用while循環求1~100的和。
???(1)用gedit編輯腳本程序test14
[root@localhost??bin]#gedit test13
total =0
num=0
???while((num<=100));
do
??????total=’expor $total +$ num’
done
echo “The result is $total”
(2)設置權限
[root@localhost??bin]#chmod +x test14
??????(3)執行
[root@localhost??bin]#./ test14
The result is 5050
12-6-3?until循環
???語法:
until?表達式
do
操作
done
重復do和done之間的操作直到表達式成立為止。
實例?12-16:用until循環求1~100的和。
???(1)用gedit編輯腳本程序test15
[root@localhost??bin]#gedit test15
total =0
num=0
???until [$sum –gt 100]
???do
???????total=’expor $total +$ num’
???????num=’expr $num +?1’
done
echo “The result is $total”
(2)設置權限
[root@localhost??bin]#chmod +x test15
??????(3)執行
[root@localhost??bin]#./ test15
The result is 5050
???????????????????????????????12-7??條件結構語句
- Shell的條件結構語句
Shell程序中的條件語句主要有if語句與case語句。
12-7-1??if語句
語法:
if?表達式1??then
操作
elif表達式2??then
操作
elif表達式3??then
操作
……
else
操作
fi
?
Linux里的if的結束標志是將if反過來寫成fi;而elif其實是else if的縮寫。其中,elif理論上可以有無限多個。
實例?12-17:用for循環求1~100的和。
(1)用gedit編輯腳本程序test16
[root@localhost??bin]#gedit test16
for((j=0;j<=10;j++))
??do
???????if(($j%2==1))
???????then
?????????echo “$j”
fi
done
(2)設置權限
[root@localhost??bin]#chmod +x test16
(3)執行
[root@localhost??bin]#./ test16
13579
12-7-2??case語句
??????語法:
case?表達式?in
值1|值2)
操作;;
值3|值4)
操作;;
值5|值6)
操作;;
*)
操作;;
esac
????case的作用就是當字符串與某個值相同是就執行那個值后面的操作。如果同一個操作對于多個值,則使用“|”將各個值分開。在case的每一個操作的最后面都有兩個“;;”分號是必需的。
實例?12-18:Linux是一個多用戶操作系統,編寫一程序根據不同的用戶登錄輸出不同的反饋結果。
?(1)用vi編輯腳本程序test17
[root@localhost??bin]#gedit test17
??#!/bin/sh
??case $USER in
beechen)
?echo “You are beichen!”;;
liangnian)
????echo “You are liangnian”;????????//注意這里只有一個分號
??echo “Welcome !”;;????????????//這里才是兩個分號
?root)
??echo “You are root!”;echo “Welcome !”;;
????//將兩命令寫在一行,用一個分號作為分隔符
*)
??echo “Who are you?$USER?”;;
easc
(2)設置權限
[root@localhost??bin]#chmod +x test17
(3)執行
[root@localhost??bin]#./ test17
You are root
Welcome!
12-8??在Shell腳本中使用函數
???
- Shell的函數
Shell程序也支持函數。函數能完成一特定的功能,可以重復調用這個函數。
?????函數格式如下:
函數名( )
?{
函數體
??}
函數調用方式為
函數名??參數列表
實例?12-19:編寫一函數add求兩個數的和,這兩個數用位置參數傳入,最后輸出結果。
(1)編輯代碼
[root@localhost??bin]#gedit test18
#!/bin/sh
add()
{
a=$1
b=$2
z=’expr $a + $b’
echo “The sum is $z”
}
add $1 $2
(2)設置權限
[root@localhost??bin]#chmod +x test18
??(3)執行
[root@localhost??bin]#./ test18??10??20
The sum is 30
?注意:
函數定義完成后必須同時寫出函數的調用,然后對此文件進行權限設定,在執行此文件。
????????????12-9??在Shell腳本中調用其他腳本
???
- Shell腳本的調用
在Shell腳本的執行過程中,Shell腳本支持調用另一個Shell腳本,調用的格式為:
?????程序名
實例?12-20:在Shell腳本test19中調用test20。
(1)調用test20
#test19腳本
#!/bin/sh
echo “The main name is $0”
./test20
echo “The first string is $1”
#test20腳本
#!/bin/sh
echo “How are you $USER?”
(2)設置權限
[root@localhost??bin]#chmod +x test19
[root@localhost??bin]#chmod +x test20
(3)執行
[root@localhost??bin]#./ test19 abc123
The main name is ./test19
How are you root?
the first string is abc123
?注意:
1)在Linux編輯中命令區分大小寫字符。
2)在Shell語句中加入必要的注釋,以便以后查詢和維護,注釋以#開頭。
3)對Shell變量進行數字運算時,使用乘法符號“*”時,要用轉義字符“\”進行轉義。
4)由于Shell對命令中多余的空格不進行任何處理,因此程序員可以利用這一特性調整程序縮進,達到增強程序可讀性效果。
5)在對函數命名時最好能使用有含義且能容易理解的名字,即使函數名能夠比較準確地表達函數所完成的任務。同時建議對于較大的程序要建立函數名和變量命名對照表。
?????????????????????????????12-10本章小結
本章講解了Linux下Shell腳本的定義和相關Shell腳本編寫的基礎,這些基礎知識是學習Shell腳本編程的關鍵。接著講解了Shell?腳本的執行方式和Shell腳本的常見流程控制,為Shell腳本的編程做了準備。
課后習題
?
?
A.安裝軟件包fctix-3.4.tar.bz2,要按順序使用./configure;make;make install;tar命令
B.掛載U盤,mount /dev/sda??/mnt/u??-o??iocharset=gb2312
C.顯示變量PS1的值用命令?echo??PS1????
D.用命令./abc與sh abc執行Shell腳本abc,所得的結果并不相同
A. #!/bin/BashB. #/bin/BashC. #/bin/cshD. /bin/Bash
A. fold??????????B. join??????????C. tr?????????????D. read
A. -2-time???????B. _2$3????????C. trust_no_1??????D. 2004file
A.?為變量賦值:$FRUIT=apple?????B.?顯示變量的值:fruit=apple
C.?顯示變量的值:echo $FRUIT????D.?判斷變量是否有值:[ -f “$FRUIT” ]
A. Shell腳本程序以文本的形式存儲
B. Shell腳本程序在運行前需要進行編譯
C. Shell腳本程序由解釋程序解釋執行
D. Shell?腳本程序主要用于系統管理和文件操作,它能夠方便自如地處理大量重復
性的系統工作
A.?程序后攜帶了兩個位置參數
B.?宏替換
C.?程序后面攜帶的第二個位置參數
D?攜帶位置參數的個數
E?用$2引用第二個位置參數
A. run.sh??????B. file1??????C. file2???????D. file3
- 在下午4 :50刪除/abc目錄下的全部子目錄和全部文件;
- 從早8:00~下午6:00每小時讀取/xyz目錄下x1文件中每行第一個域的全部數據加入到/backup目錄下的bak01.txt文件內;
- 每逢星期一下午5:50將/data目錄下的所有目錄和文件歸檔并壓縮為文件:backup.tar.gz;
- 在下午5:55將IDE接口的CD-ROM卸載(假設:CD-ROM的設備名為hdc);
- 在早晨8:00前開機后啟動。
?
課程實訓
實訓內容:編寫一個Shell程序,呈現一個菜單,有0-5共6個命令選項,1為掛載U盤,2為卸載U盤,3為顯示U盤的信息,4把硬盤中的文件拷貝到U盤,5把U盤中的文件拷貝到硬盤中,選0為退出。
程序分析:把此程序分成題目中要求的6大功能模塊,另外加一個菜單顯示及選擇的主模板。
?[root@localhost??bin]#vi test19
#!/bin/sh
#mountusb.sh
#退出程序函數
quit()
{
??clear
??echo “*******************************************************************”
??echo??“***???????????thank you to use,Good bye!????????????****”
??exit 0
??}
?#加載U盤函數
?mountusb()
?{
??clear
??#在/mnt下創建usb目錄
??mkdir /mnt/usb
??#查看U盤設備名稱
??/sbin/fdisk –l |grep /dev/sd
??echo –e “Please Enter the device name of usb as shown above:\c”
read PARAMETER
mount /dev/$PARAMETER /mnt/usb
}
#卸載U盤函數
umountusb()
{
??clear
??ls -la /mnt/usb
}
#顯示U盤信息函數
display()
{
??clear
??umount /mnt/usb
}
#拷貝硬盤文件到U盤函數
cpdisktousb()
{
???clear
???echo –e “Please Enter the filename to be Copide (under Current directory):\c”
???read FILE
???echo “Copying,please wait!...”
???cp $FILE /mnt/usb
}
#拷貝U盤函數到硬盤文件
cpusbtodisk()
{
??clear
??echo -e “Please Enter the filename to be Copide in USB:\c”
??read FILE
??echo “Copying ,Please wait!...”
??cp /mnt/usb/$FILE .??#點(.)表示當前路徑
}
??clear
??while true
??do
echo “=====================================================================”
echo “***????????????LINUX USB MANAGE PROGRAM?????????????????????***”
echo??“??????????????1-MOUNT USB????????????????????????????????????”
echo??“??????????????2-UNMOUNT USB??????????????????????????????????”
echo??“??????????????3-DISPLAY USB INFORMATION??????????????????????”
echo??“??????????????4-COPY FILE IN DISK TO USB?????????????????????”
echo??“??????????????5-COPY FILE IN USB TO DISK?????????????????????”
echo??“??????????????0-EXIT?????????????????????????????????????????”
echo “=====================================================================”
echo –e “Please Enter a Choice(0-5):\c”
read CHOICE
case $CHOICE in
*)??echo “Invalid Choice!Corrent Choice is (0-5)”
????sleep 4
????clear;;
?esac
done
(2)修改權限
[root@localhost??bin]#chmod +x test19
(3)程序執行結果
[root@localhost??bin]#./ test19
項目實踐
這段時間陳飛在學習Linux下的Shell?編程,感覺Shell?編程和C語言很相似。王工程師今天來看陳飛,順便問一下陳飛的學習情況。陳飛就和他說了自己對Shell編程的看法。王工程師聽了后,笑著說,“一樣不一樣,你編個程序不久明白了嗎。”“那編什么程序呢”。陳飛問道。“就俄羅斯方塊吧”,王工程師說?!岸砹_斯方塊大家都會玩,而且你可以在網上找到用C語言編寫的程序,你用Shell編程實現,和C語言版的對比一下,不就明白了它們之間的不同了嗎”。王工程師走了,留下了陷入沉思的陳飛。他能完成嗎?
總結
以上是生活随笔為你收集整理的linux Shell(脚本)编程入门实例讲解详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell脚本例子集锦
- 下一篇: Linux TCP队列相关参数的总结