Linux程序設(shè)計(jì)2-第二章Shell程序設(shè)計(jì)_第1頁
Linux程序設(shè)計(jì)2-第二章Shell程序設(shè)計(jì)_第2頁
Linux程序設(shè)計(jì)2-第二章Shell程序設(shè)計(jì)_第3頁
Linux程序設(shè)計(jì)2-第二章Shell程序設(shè)計(jì)_第4頁
Linux程序設(shè)計(jì)2-第二章Shell程序設(shè)計(jì)_第5頁
已閱讀5頁,還剩68頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第二章Shell程序設(shè)計(jì)基本要求1、了解什么是shell;2、掌握創(chuàng)建和執(zhí)行Shell腳本,Shell程序設(shè)計(jì)的語法。Shell腳本的概念在Linux下,Shell腳本廣泛用于系統(tǒng)管理和軟件開發(fā),是Linux系統(tǒng)管理員和開發(fā)人員必備知識之一.bash或稱BourneAgainshell:標(biāo)準(zhǔn)的GNUshell,直觀而又靈活。或是初學(xué)者的最明智選擇同時(shí)對高級和專業(yè)用戶來說也是一個(gè)強(qiáng)有力的工具在Linux上,bash是普通用戶的標(biāo)準(zhǔn)shell這個(gè)shell因此稱為Bourneshell的超集,一套附件和插件。意味bash和sh是兼容的:在sh中可以工作的命令,在bash中也能工作,反之則不然.用cat/etc/shells可以顯示系統(tǒng)安裝的ShellShell腳本的概念LinuxShell腳本是多個(gè)Linux命令的集合,是一個(gè)具有執(zhí)行權(quán)限的文本文件Shell腳本是一個(gè)寫入系列命令文本文件里,可以一次性執(zhí)行的可執(zhí)行文件Linux大量采用Shell腳本來完成重復(fù)性或系統(tǒng)維護(hù)工作Shell腳本類似于Windows的批處理文件(*.bat)但是功能遠(yuǎn)強(qiáng)于它.可以用vi創(chuàng)建腳本,也可以用其它文本工具創(chuàng)建后上傳到Linux.在Windows下可以UltraEdit保存成Unix文本格式BashShell腳本與CShell腳本語法有差別,本章主要采用BashShell語法.Shell腳本必須有執(zhí)行權(quán)限Shell腳本格式Shell腳本必須為Linux文本文件Shell腳本的第一句必須指定解釋的Shell通常固定為#!/bin/shShell中,以井號(#)開始一個(gè)注釋行,#號及其后面跟隨的同一行的所有內(nèi)容都被忽略腳本必須有可執(zhí)行權(quán)限chmodu+xmyscript

由所有者執(zhí)行chmoda+xmyscript

同組加上可執(zhí)行權(quán)限chmod777myscript

全部用戶加上可執(zhí)行權(quán)限$,*,’,\是腳本保留字符,如果需要作為顯示字符,則需要在前面加入轉(zhuǎn)義字符\,如\\,\*,\$,\’Shell變量Shell可以使用變量,對Shell而言,所有變量值都是字符串類型Shell變量,分為三大類:系統(tǒng)變量,環(huán)境變量,用戶自定義變量所有變量不需要自定義可以直接使用系統(tǒng)變量是指BashShell內(nèi)部定義的保留變量環(huán)境變量可以看成是在整個(gè)Shell的各個(gè)程序都能訪問的全局變量用戶自定義變量由用戶自行定義.定義格式為變量名=值,等號兩邊不能有空格,引用時(shí)用$myvar=“Hello,world”#定義一個(gè)變量myvar=“hello”#錯(cuò)誤定義,等號兩邊帶了空格變量的引用和顯示變量通過$來引用值A(chǔ)=“123”$A的值就是”123”,并且在運(yùn)行中可以改變變量值的顯示主要通過echo命令A(yù)=100;echo$A在LinuxShell腳本里,字符串‘’和””表示不同的含義,最大區(qū)別就是在于對變量引用的處理.單引號‘’包括之中表示字符串,如果字符串包含保留字符,則保留字符失效,按原樣輸出x=5;echo‘x=$x’

輸出x=$x雙引號“”包括之中表示字符串,如果字符串包含保留字符,則保留字符生效,如變量要顯示變量值x=5;echo“x=$x”

輸出x=5變量引用實(shí)例(456)#!/bin/sh

myvar="Hello,world"

echo1=$myvar

echo2="$myvar"

echo3='$myvar'

echo4=\$myvar

echo5=\'$myvar\'

echo6="'$myvar'"

echo7='"$myvar"'

echo8=\"$myvar\"執(zhí)行腳本注意當(dāng)前路徑不在環(huán)境變量PATH當(dāng)中。換句話在當(dāng)前目錄執(zhí)行某一個(gè)程序(如a.sh),必須要加../a.sh這樣主要出于安全考慮變量名保護(hù)在shell中,由于書寫比較隨意,很容易造成變量名引寫錯(cuò)情況.由于Shell不需要變量定義,所以非常容易出錯(cuò).var1書寫成$var1hello,這樣形成新的變量Shell可以用{}來保護(hù)變量的引用var1=hello;echo${var1}hello變量值的賦值(12378)shell變量不需定義即可使用,這樣對變量值初始值就有一些問題,Shell提供一些簡單的判斷或初始化機(jī)制Var=value變量賦值${variable:-value}空值置換如果變量已經(jīng)賦值,則使用該變量值。如果變量為空,則整個(gè)引用值使用value。需要注意的是,value并不賦給variable。var3=11;echo${var3:-12}類似于C語言的var3==NULL?12:var3表達(dá)echo${var3:-12}${variable:=value}空值賦值該表達(dá)式上面的區(qū)別就是,如果variable為空,則value賦給variable。echo${var4:=12};echo$var4${variable:?}空值出錯(cuò)檢驗(yàn)變量是否為空,如果為空的話則顯示帶有系統(tǒng)錯(cuò)誤信息${variable:?"customedmessage"}檢驗(yàn)變量是否為空,如果為空的話則顯示自定義錯(cuò)誤信息${variable:+word}有值置換

-變量被賦值的情況下置換一個(gè)值

echo${DEBUG:+”Debugisactive.”}Shell環(huán)境變量shell環(huán)境變量是所有shell程序都會接受的參數(shù)PATH 命令搜索路徑,以冒號為分隔符.注意與DOS下不同的是,當(dāng)前目錄不在系統(tǒng)路徑里HOME 用戶home目錄的路徑名,是cd命令的默認(rèn)參數(shù)IFS 定義SHELL使用的分隔符,指命令行參數(shù)分隔符IFS=$'\t\n'LOGNAME 用戶登錄名SHELL SHELL的路徑名TERM 終端類型LD_LIBRARY_PATH尋找?guī)斓穆窂?以冒號分隔定義自定義環(huán)境變量exportMY_NAME=AndrewexportPATH=/home/hxy/bin:$PATH如果每次啟動想使用自定義環(huán)境變量,需要修改home目錄下~/.bash_profile文件,可以ls–al查看取消環(huán)境變量和自定義變量用unset變量名如unsetUSERShell環(huán)境變量規(guī)定一個(gè)程序在Shell下被執(zhí)行,那么首先是在這個(gè)Shell下創(chuàng)建一個(gè)子shell.在這個(gè)子Shell再執(zhí)行程序。子Shell所有變量從上一級Shell繼承下來程序/腳本修改子Shell的環(huán)境變量。父Shell不受影響,這個(gè)主要為了安全考慮。Shell系統(tǒng)變量常用系統(tǒng)變量$n $1表示第一個(gè)參數(shù),$2表示第二個(gè)參數(shù)...$# 命令行參數(shù)的個(gè)數(shù)$0 當(dāng)前程序的名稱$? 前一個(gè)命令或函數(shù)的返回碼$* 以“參數(shù)1參數(shù)2...”

形式保存所有參數(shù)$@ 以“參數(shù)1”

“參數(shù)2”...形式保存所有參數(shù)$$ 本程序的(進(jìn)程ID號)PID$! 上一個(gè)命令的PID系統(tǒng)變量的實(shí)例./sys_var.shAndrewhxy#!/bin/sh#Thisfileisusedtoexplaintheshellsystemvariable.echo"thenumberofparameteris$#";echo"thereturncodeoflastcommandis$?";echo"thescriptnameis$0";echo"theparametersare$*";xxx=10echo"\$1=$1;\$2=$2";echo"\$*=$*"echo"\$@=$@"Shell表達(dá)式運(yùn)算Shell用$((expr))

來進(jìn)行表達(dá)式運(yùn)算echo$((1+3))它等效于let命令,即letexpr等效于$((expr))letx=1+3;echo$x$(())支持多種進(jìn)制表示echo$((013))#八進(jìn)制echo$((0xA4))#十六進(jìn)制任意進(jìn)制表示$((進(jìn)制#數(shù)))echo$((2#1101010))#2進(jìn)制表示echo$((8#377))#8進(jìn)制表示echo$((16#D8))#16進(jìn)制表示echo$((12#10))#12進(jìn)制表示echo$((36#ZZYY))#36進(jìn)制表示支持運(yùn)算符+-*\%<><=>=<<>>expr把后面字符串當(dāng)成數(shù)學(xué)表達(dá)式計(jì)算注意每個(gè)數(shù)之間的空格expr2+4expr3\*5VAR=`expr2+4`#這里是`,即ESC下面鍵,不是’流程控制:條件語句If判斷命令語法結(jié)構(gòu)ifTEST-COMMANDS;thenCONSEQUENT-COMMANDS;[elseELSE-Commnds;]fi

注意上面在寫在一整行里的,所以在ifthenfi三個(gè)命令之間要加入;如果是多行定義;不是必要的,如下面定義ifTEST-COMMANDSthenCONSEQUENT-COMMANDSfi

TEST-COMMANDS多是一些固定檢測,包含在test或[]之中,在下一節(jié)會詳細(xì)講解[-aFILE]

如果FILE存在則為真。Test–aFILEtest-zSTRING

“STRING”

的長度為零則為真。if/then/elif/fi用來表示更復(fù)雜的結(jié)構(gòu),這跟C語言的的if()elseif()類似if/then/else/fi可以簡化成[expr]&&true_command||false_command,這樣更簡潔,但也更能看懂[-ahello.txt]&&echotrue||echofalse等同于If[-ahello.txt];thenechotrue;elseechofalse條件判斷式我們來看繁多的test測試表達(dá)式,他們出現(xiàn)if,while,case的條件判斷位置.條件表達(dá)式是有兩種等效的格式,一種是testexpr,還是有一種是[expr],test內(nèi)嵌命令會根據(jù)對表達(dá)式expr的計(jì)算結(jié)果來確定返回0(成功)或1(失?。?梢酝ㄟ^顯示$?來檢查返回值在這里test,[,]都是命令!換句話說,它們必須與expr要隔著至少一個(gè)空格.象C語言一樣[expr]的書寫是錯(cuò)誤的,而且從錯(cuò)誤提示中很難看出這個(gè)問題來.這是C開發(fā)者要特別注意的.后面都是以[]為例來講解條件判斷表?xiàng)l件判斷分為幾大類文件判斷運(yùn)算符,主要用于判斷文件類型或是否存在的條件字符串比較運(yùn)算符,主要為比較字符串是否相同算術(shù)比較運(yùn)算符,主要和于判斷兩個(gè)數(shù)之間大小關(guān)系條件判斷式(續(xù))運(yùn)算符描述示例文件比較運(yùn)算符-efilename如果filename存在,則為真[-e/var/log/syslog]-dfilename如果filename為目錄,則為真[-d/tmp/mydir]-ffilename如果filename為常規(guī)文件,則為真[-f/usr/bin/grep]-Lfilename如果filename為符號鏈接,則為真[-L/usr/bin/grep]-rfilename如果filename可讀,則為真[-r/var/log/syslog]-wfilename如果filename可寫,則為真[-w/var/mytmp.txt]-xfilename如果filename可執(zhí)行,則為真[-x/usr/bin/grep]filename1-ntfilename2如果filename1比filename2新,則為真[/tmp/install/etc/services-nt/etc/services]filename1-otfilename2如果filename1比filename2舊,則為真[/boot/bzImage-otarch/i386/boot/bzImage]條件判斷式(續(xù))運(yùn)算符描述示例字符串比較運(yùn)算符(請注意引號的使用,這是防止空格擾亂代碼的好方法)-zstring如果string長度為零,則為真[-z"$myvar"]-nstring如果string長度非零,則為真[-n"$myvar"]string=string2如果string1與string2相同,則為真["$myvar"="onetwothree"]string1!=string2如果string1與string2不同,則為真["$myvar"!="onetwothree"]算術(shù)比較運(yùn)算符num1-eqnum2等于[3-eq$mynum]num1-nenum2不等于[3-ne$mynum]num1-ltnum2小于[3-lt$mynum]num1-lenum2小于或等于[3-le$mynum]num1-gtnum2大于[3-gt$mynum]Num1-genum2大于或等于[3-ge$mynum]條件判斷實(shí)例test3-gt4&&echoTrue||echofalse判斷3是否大于4if[$?-eq0];thenecho'Thatwasagoodjob!';if判斷上一個(gè)程序返回值是否為0test-d"$HOME";echo$?判斷用戶的主目錄是否存在test"abc"="def";echo$?判斷兩個(gè)字符串是否相等[-fhello.txt];echo$?判斷文件hello.txt是否存在If實(shí)例對上一個(gè)命令返回值作判斷#查找本地密碼文件是否包含當(dāng)前用戶grep$USER/etc/passwdif[$?-ne0];thenecho"notalocalaccount";fi檢測腳本執(zhí)行是否有參數(shù)if[$#-eq0];thenecho"$0noparameter">&2exit1fi字符串比較if["$(whoami)"!='root'];thenecho"Youhavenopermissiontorun$0asnon-rootuser."exit1;fi上面等效于["$(whoami)"!='root']&&(echoyouareusinganon-privilegedaccount;exit1)流程控制:多向分支Case語句類似于C語言中的switch多向分支sase語法結(jié)構(gòu)

case字符串in;模式1)command;;模式2)command;;esacC語言開發(fā)者又要注意了,模式后是)而不是:因?yàn)?也是保留字,而且執(zhí)行語句后面是;;這還是單行定義語句,多行定義如下

case字符串in

模式1)command;;模式2)command;;

…esac模式可以用多個(gè)值,用|隔開1|2|3|8|9)case實(shí)例,菜單選擇#Displayamenuecho_echo"1Restore"echo"2Backup"echo"3Unload"echo#Readandexcutetheuser'sselectionecho-n"EnterChoice:"readCHOICEcase"$CHOICE"in1)echo"Restore";;2)echo"Backup";;3)echo"Unload";;*)echo"Sorry$CHOICEisnotavalidchoice“exit1

esac*)表示類似于C語言的default分支模式可以是正則表達(dá)式,或通配符*.txt[ab].out復(fù)雜實(shí)例流程控制:bash循環(huán)機(jī)制Bash支持三種循環(huán)for

循環(huán)有兩種形式。shell腳本編程中最常見的形式是對一組值進(jìn)行迭代,對每個(gè)值都執(zhí)行命令列表一次。這組值可能為空,在這種情況下命令列表就不會被執(zhí)行。另外一種形式更加類似于傳統(tǒng)的Cfor循環(huán),使用3個(gè)數(shù)學(xué)表達(dá)式來控制循環(huán)的起始條件、步進(jìn)函數(shù)和結(jié)束條件。while

循環(huán)每次都在循環(huán)開始時(shí)計(jì)算一個(gè)條件的值,如果這個(gè)條件為true,就執(zhí)行命令列表。如果這個(gè)條件最初不為true,那么這些命令就永遠(yuǎn)都不會執(zhí)行。until

循環(huán)執(zhí)行一個(gè)命令列表,并在每個(gè)循環(huán)結(jié)束時(shí)計(jì)算某個(gè)條件的值。如果這個(gè)條件為true,就再次執(zhí)行這個(gè)循環(huán)。即使條件最初不為true,這些命令也會至少被執(zhí)行一次。

流程控制:for循環(huán)for循環(huán)在shell并不是象C語言累加的形式,而是采用腳本中特有的fordo格式語法結(jié)構(gòu)forNAME[inLIST];doCOMMANDS;done這里表示從LIST依次取值(以空格為界)賦給變量Name,然后執(zhí)行dodone中的命令,這跟C語言差別非常大.如果[inLIST]

不存在的話,就使用in$@

替換且for

對每個(gè)位置參數(shù)執(zhí)行一次COMMANDS,$@是指命令行參數(shù)列表例子:

forxinabd2"mystuff";doecho$x;done如果想for實(shí)現(xiàn)象C中循環(huán)累加的結(jié)果需要用到$(())表達(dá)式for((x=2;x<5;x++));doecho$x;donefor實(shí)例#!/usr/bin/envbash#取得/etc/目錄下所有以r打頭的文件名,判斷是不是目錄

formyfilein/etc/r*doif[-d"$myfile"]thenecho"$myfile(dir)"elseecho"$myfile"fidone流程控制:while循環(huán)while

結(jié)構(gòu)允許重復(fù)執(zhí)行一系列命令,只要控制while

循環(huán)的命令執(zhí)行成功(退出狀態(tài)是零)語法格式whileCONTROL-COMMAND;doCONSEQUENT-COMMANDS;doneCONTROL-COMMAND采用if同樣的判斷test表達(dá)式這里while,do,done都是命令,在一行內(nèi)要;隔開while實(shí)例X=1while((X<=10))do echohelloXis$X letX=X+1done流程控制:util循環(huán)重復(fù)循環(huán)直到條件為真為止。until

循環(huán)和while

循環(huán)非常相似,但是正好相反,除了循環(huán)執(zhí)行直到TEST-COMMAND

執(zhí)行成功。只要這個(gè)命令測試失敗,循環(huán)就繼續(xù)。untilTEST-COMMAND;doCONSEQUENT-COMMANDS;doneutil表達(dá)式X=1until((X>10))do echohelloXis$X letX=X+1doneShift命令很多時(shí)候,變量值是一組以空格隔開的列表,如命令行參數(shù),一組文件名列表等等.在循環(huán)中可能需要逐一處理.C語言只能數(shù)組加下標(biāo),或指針變量移動來處理.那Shell腳本呢,當(dāng)然開發(fā)者可以自己處理字符串,一個(gè)一個(gè)把值分離出來,但是在Shell腳本里有更簡單辦法.使用Shift命令來處理.Shift命令每次把從命令行參數(shù)位置變量值取一個(gè)值出來,并且把總數(shù)減一.這樣處理循環(huán)起來非常簡單shift后可加整數(shù)進(jìn)行一次多個(gè)移位shift3shift實(shí)例注意命令行參數(shù)總數(shù),$#每shift一次,值減一.#利用shift計(jì)算所有參數(shù)乘積,假設(shè)參數(shù)均為整數(shù)#!/bin/shresult=1while[$#-gt0]doresult=`expr$result\*$1`shiftdoneecho$result#打印所有命令行參數(shù)until[$#-eq0];doecho“para=$1count$#"

shiftdone循環(huán)跳轉(zhuǎn)機(jī)制exit,break和continue

跳出機(jī)制這些機(jī)制跟C語言是一樣的,可用于if和循環(huán)中.都是用于提前跳出break[n]中止循環(huán)過程的執(zhí)行,并且跳到下一個(gè)命令。N表示跳出嵌套的層數(shù)continue[n]停止循環(huán)過程的當(dāng)前一個(gè)反復(fù)并且跳到循環(huán)中的下一個(gè)反復(fù)過程的開始部分,n表示忽略的層數(shù)exit[n]停止shell程序的執(zhí)行,并且將返回值設(shè)置為n。break命令讓您可以從一個(gè)循環(huán)中立即退出。如果使用了嵌套循環(huán),也可以指定退出的層次數(shù)。因此如果在for循環(huán)中有一個(gè)until循環(huán),而這個(gè)for循環(huán)在另外一個(gè)for循環(huán)之中,所有這些循環(huán)又全部在一個(gè)while循環(huán)中,那么break

3就會立即結(jié)束until循環(huán)和2個(gè)for循環(huán),并將控制權(quán)返回給while循環(huán)中的代碼continue語句可以跳過命令列表中的剩下的語句,直接跳轉(zhuǎn)到下一次循環(huán)的開頭continue和break的應(yīng)用while

truedo

echo"Enterfiletoremove:c"

readFILE

iftest!-f$FILE

then

echo$FILEisnotaregularfile

continue

fi

echoremoving$FILE

rm$FILE

breakdone建立交互式腳本(1)用echo來輸出信息read接收用戶的輸入使用內(nèi)建命令read,它從標(biāo)準(zhǔn)輸入讀取變量的值,讀入單行輸入并將各個(gè)輸入詞分配給各個(gè)變量readVAR;echo$VAR使用-p選項(xiàng)為每次read提供提示。使用以引號括起來的字符串提供提示read-p"Insteadof$VAR,whatnumberwouldyoulike?"VAR;$echoVAR從管道里讀取ls|whilereadfile;dols$file;done

read可一次性讀取多個(gè)變量ls-i|whilereadinodefile;do\echo"File$filehasinode$inode";done交互式菜單#!/bin/bashecho"*******************************"echo"Pleaseselectyouroperation:"echo"1Copy"echo"2Delete"echo"3Backup"echo"*******************************"readopcase$opinC)echo"yourselectionisCopy";;D)echo"yourselectionisDelete";;B)echo"yourselectionisBackup";;*)echo"invalidselection"esac建立交互式腳本(2)select表達(dá)式是一種bash的擴(kuò)展應(yīng)用,用戶可以從一組不同的值中進(jìn)行選擇.語句結(jié)構(gòu):selectvarin...;do

breakdone$var存儲用戶所選的值select實(shí)例#!/bin/shecho"WhatisyourfavouriteOS?"selectvarin"Linux""GnuHurd""FreeBSD""Other";dobreakdoneecho"Youhaveselected$var"使用函數(shù)腳本的函數(shù)比較受限制不能單獨(dú)寫在一個(gè)腳本里,至少有一個(gè)調(diào)用語句定義function_name(){...}函數(shù)用return返回值函數(shù)參數(shù)也采用$1,$2之類進(jìn)行傳輸show(){echo"show$*"}echo$*echo"afterfunction"showcdecho$*函數(shù)實(shí)例#!/usr/bin/envbash

myvar="helloheh"

myfunc(){localxlocalmyvar="onetwothree"forxin$myvardoecho$xdone}

myfunc

echo$myvar$x簡單腳本調(diào)試簡單一般用echo直接輸出內(nèi)部變量,復(fù)雜一點(diǎn)采用trap命令也在腳本執(zhí)行時(shí)加入-x參數(shù)sh–xmenu1.sh#sh是Shell程序名字,表示運(yùn)行menu1.sh并顯示內(nèi)部變量值或bash–xmenu1.sh也可執(zhí)行該腳本并顯示所有變量的值。不執(zhí)行,只執(zhí)行語法檢查-n參數(shù)sh–nmenu1.sh不報(bào)錯(cuò)表示沒有錯(cuò)誤用trap調(diào)試腳本trap命令用于捕獲指定的信號并執(zhí)行預(yù)定義的命令。其基本的語法是:

trap‘command’

signal其中signal是要捕獲的信號,command是捕獲到指定的信號之后,所要執(zhí)行的命令??梢杂胟ill–l命令看到系統(tǒng)中全部可用的信號名,捕獲信號后所執(zhí)行的命令可以是任何一條或多條合法的shell語句,也可以是一個(gè)函數(shù)名。shell腳本在執(zhí)行時(shí),會產(chǎn)生三個(gè)所謂的“偽信號”,(之所以稱之為“偽信號”是因?yàn)檫@三個(gè)信號是由shell產(chǎn)生的,而其它的信號是由操作系統(tǒng)產(chǎn)生的),通過使用trap命令捕獲這三個(gè)“偽信號”并輸出相關(guān)信息對調(diào)試非常有幫助。Shell偽信號

EXIT從一個(gè)函數(shù)中退出或整個(gè)腳本執(zhí)行完畢

ERR當(dāng)一條命令返回非零狀態(tài)時(shí)(代表命令執(zhí)行不成功

DEBUG腳本中每一條命令執(zhí)行之前trap調(diào)試腳本通過捕獲EXIT信號,我們可以在shell腳本中止執(zhí)行或從函數(shù)中退出時(shí),輸出某些想要跟蹤的變量的值,并由此來判斷腳本的執(zhí)行狀態(tài)以及出錯(cuò)原因,其使用方法是:trap'command'EXIT或trap'command'0通過捕獲ERR信號,我們可以方便的追蹤執(zhí)行不成功的命令或函數(shù),并輸出相關(guān)的調(diào)試信息,以下是一個(gè)捕獲ERR信號的示例程序,其中的$LINENO是一個(gè)shell的內(nèi)置變量,代表shell腳本的當(dāng)前行號。trap'ERRTRAP$LINENO'ERRtrap調(diào)試腳本在調(diào)試過程中,為了跟蹤某些變量的值,我們常常需要在shell腳本的許多地方插入相同的echo語句來打印相關(guān)變量的值,這種做法顯得煩瑣而笨拙。而通過捕獲DEBUG信號,我們只需要一條trap語句就可以完成對相關(guān)變量的全程跟蹤。trap'echo“beforeexecuteline:$LINENO,a=$a,b=$b,c=$c”'DEBUG

trapERR實(shí)例ERRTRAP(){echo"[LINE:$1]Error:Commandorfunctionexitedwithstatus$?“}foo(){return1;}trap'ERRTRAP$LINENO'ERRabcfooTrapEXITERRTRAP(){echo"[LINE:$1]Error:Commandorfunctionexitedwithstatus$?“}foo(){return1;}trap'ERRTRAP$LINENO'EXITabcfooTrapDebug#!/bin/bashtrap'echo"beforeexecuteline:$LINENO,a=$a,b=$b,c=$c"'DEBUGa=1if["$a"-eq1]Thenb=2Elseb=1Fic=3echo"End"例:Service腳本/sbin/service用于控制各種服務(wù)的啟動和停止#!/bin/sh#Setupadefaultsearchpath.PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin"exportPATHVERSION="`basename$0`ver.0.91"USAGE="Usage:`basename$0`<option>|--status-all|\[service_name[command|--full-restart]]"SERVICE=SERVICEDIR="/etc/init.d"OPTIONS=if[$#-eq0];then#判斷參數(shù)是否0,腳本要求必須有參數(shù)

echo$"${USAGE}">&2exit1fi

復(fù)雜腳本樣例1.檢測某個(gè)進(jìn)程是否正常工作check_process.sh2.檢測磁盤空間是否足夠,并報(bào)警check_disk.sh列出目錄樹#!/bin/sh

#dtree:Usage:dtree[anydirectory]

dir=${1:-.}

find$dir-typed-print|sort-f|sed-e"s,^$1,,"-e"/^$/d"-e"s,[^/]*/([^/]*)$,’----1’,"-e"s,[^/]*/,|,g"

init腳本例子一個(gè)init腳本啟動在UNIX和Linux機(jī)器上的系統(tǒng)服務(wù)存儲在系統(tǒng)的特定位置,比如/etc/rc,/etc/rc.d/init.d或者/etc/init.d目錄下awk2、awk模式模式可匹配特定行,可以是以下任意一個(gè):/正則表達(dá)式/:如awk'/[0-9]+\.[0-9]*/{print}'file關(guān)系表達(dá)式:如awk'$1=="fred"{print$3}'file模式匹配表達(dá)式:如awk'$5~/root/{print}'file3、awk操作操作位于{}內(nèi),由換行符或分號隔開,對匹配的行進(jìn)行操作,包括:變量或數(shù)組賦值輸出命令:如printprintf內(nèi)置函數(shù):如splitindexmatchsubstr等控制流命令:如ifforwhile等1、awk腳本組成awk腳本是由模式和操作組成的:awk‘BEGIN{print“start”}pattern{commands}END{print“end”}’fileawk4、awk內(nèi)置變量ARGC:命令行參數(shù)個(gè)數(shù)ARGV:命令行參數(shù)數(shù)組ARGIND:當(dāng)前文件索引(從1開始)FILENAME:當(dāng)前輸入文件名FS:輸入字段分隔符(默認(rèn)空格)NR:當(dāng)前記錄數(shù)NF:當(dāng)前記錄字段數(shù)OFS:輸出字段分隔符(默認(rèn)空格)ORS:輸出記錄分隔符(新行)RS:輸入記錄分隔符(新行)RSTART:被匹配函數(shù)匹配的字符串首RLENGTH:被匹配函數(shù)匹配的字符串長度OFMT:數(shù)字的輸出格式(%.6g)IGNORECASE:控制大小寫敏感(0:敏感)awk-F'%''BEGIN{

OFMT="%.3g";

#輸出數(shù)字保留3位

IGNORECASE=1;

#忽略大小寫

OFS="&";

#輸出字段分隔符}{

if(match($1,/^A.*f$/)>0){

#匹配函數(shù)

printNR,NF,RSTART,RLENGTH,$2+0;}}'file#輸出1&3&1&2&2.233&4&1&4&1.32#假設(shè)file內(nèi)容如下af%2.23423%ssxxx%1.2asdf%1.323242%xx%ssawk函數(shù)名含義sub(e,r,src)將src中匹配e的第一個(gè)字串替換為rgsub(e,r,src)將src中匹配e的全部字串替換為rindex(s1,s2)返回s2在s1的索引(未找到返回0)length(s)返回s的長度substr(s,i,len)返回s中從i位置起,長度為len的字串match(s,e)返回e在s中匹配的字串的起始位置split(s,arr,sep)將s按sep分割,元素存于數(shù)組arr中tolower(s)將s轉(zhuǎn)換為小寫toupper將s轉(zhuǎn)換為大寫strftime將時(shí)間戳轉(zhuǎn)換為時(shí)間字符串注:awk函數(shù)返回的下標(biāo)從1開始,數(shù)組下標(biāo)也從1開始假設(shè)awk變量s="thisisatest2010test!"awk'BEGIN{gsub(/[0-9]+/,"!",s);prints;}'#thisisatest!test!"awk'BEGIN{printindex(info,"test");}'#11awk'BEGIN{printmatch(s,/[0-9]+/);}'#15awk'BEGIN{printsubstr(s,4,10);}'#sisatesawk'BEGIN{split(info,a,"");for(kina){printf("%s%s,",k,a[k]);}printf("\n");}'#4test,1this,2is,3a,echo`date+%s`|awk'{printstrftime("%Y-%m-%d%H:%M:%S",$0)}'#2015-04-0216:24:525、awk內(nèi)置函數(shù)awkawk-F"|"'BEGIN{#點(diǎn)擊應(yīng)用推薦行為ID

CLICK_APP_REC_ACTION_ID=321

click_user_num=0; }{for(i=1;i<=NF;i++){ split($i,arr,":");if(arr[1]==CLICK_APP_REC_ACTION_ID){click_user_num=arr[3];break; }}}END{printclick_user_num;}'${file}6、一個(gè)實(shí)例需求:統(tǒng)計(jì)點(diǎn)擊應(yīng)用推薦的用戶數(shù)文件file格式為:110:138:86|111:7:5|321:6:6|9:72:62|113:27:23|...格式含義如下:

行為ID:點(diǎn)擊次數(shù):點(diǎn)擊用戶數(shù)sedsed選項(xiàng)-n:關(guān)閉默認(rèn)輸出-r:支持?jǐn)U展正則+?(){}|-i:修改原文件,慎用!sed定址$:表示文件最后一行0個(gè):沒有定址,所有行1個(gè):行號,處理行號所在位置的行2個(gè):行號、正則表達(dá)式,處理被行號或正則表達(dá)式包起來的行sed命令p:打印行d:刪除行s:替換w:另存為a:當(dāng)前行后添加一行i:在當(dāng)前行上面插入文本1、sed簡介sed用來對文本進(jìn)行過濾與替換,一次僅讀取一行內(nèi)容。2、sed工作原理sed把當(dāng)前行存儲在臨時(shí)緩沖區(qū)中(稱為“模式空間”),用sed命令處理緩沖區(qū)中的內(nèi)容,處理完成后,把緩沖區(qū)的內(nèi)容送往屏幕。3、sed語法sed[選項(xiàng)][定址commands][inputfile]sed刪除命令:d命令$sed'2d'file

#刪除file文件的第二行$sed'2,$d'file

#刪除file文件的第二行到末尾所有行$sed'$d'file

#刪除file文件的最后一行$sed'/test/d'file

#刪除file文件所有包含test的行選定行的范圍:逗號$sed-n'/test/,/check/p'file #打印所有在模板test和check所確定的范圍內(nèi)的行$sed-n'5,/^test/p'file #打印從第五行到第一個(gè)包含以test開始的行之間的所有行$sed'/test/,/love/s/$/xxx/'file

#對于模板test和love之間的行,每行的末尾用xxx替換替換:s命令$sed's/test/xxx/g'file

#把行中所有的test替換為xxx;若無g,則只替換第一個(gè)$sed-n-r's/(love)ab/1rs/'file #love被標(biāo)記為1,所有l(wèi)oveab會被替換成lovers$sed's#10#100#g'file #“#”緊跟s后,是分隔符,代替了默認(rèn)的“/”分隔符追加命令:a命令$sed'/^test/axxxx'file

#在以test開頭的行后插入新行xxxx插入命令:i命令$sed'/^test/ixxxx'file

#在以test開頭的行前插入新行xxxx4、sed實(shí)例cutcut選項(xiàng)-b:以字節(jié)為單位顯示選中內(nèi)容-c:以字符為單位顯示選中內(nèi)容-f:以字段為單位顯示選中內(nèi)容-d:指定字段的分界符,默認(rèn)為制表符cut范圍n:第n個(gè)字段n-:從第n個(gè)到最后一個(gè)字段n-m:從第n到第m個(gè)字段,包括m-m:從第1到第m個(gè)字段,包括m-:從行開頭到行的最后n,m:第n個(gè)和第m個(gè)字段常用實(shí)例#截取指定字段$echoroot:x:0:0:root:/root:/bin/bash|cut-d:-f1,5$echoroot:x:0:0:root:/root:/bin/bash|cut-d:-f1-$echoroot:x:0:0:root:/root:/bin/bash|cut-d:-f2-4#截取指定個(gè)數(shù)的字符$echoroot:x:0:0:root:/root:/bin/bash|cut-c2-5$echoroot:x:0:0:root:/root:/bin/bash|cut-c-2$echoroot:x:0:0:root:/root:/bin/bash|cut-c2-1、cut簡介從文件的每一行剪切字節(jié)、字符和字段并將它們寫至標(biāo)準(zhǔn)輸出。2、cut語法cut[選項(xiàng)][范圍]文件tr用一個(gè)字符來替換另外一個(gè)字符刪除字符串中的指定子串合并字符串中重復(fù)串tr[option]set1set2<input-filetr選項(xiàng)默認(rèn):用str2替換str1-d:刪除str1中所有輸入字符-s:刪除重復(fù)字符序列,只保留第一個(gè)常用實(shí)例#小寫轉(zhuǎn)大寫$tr'r''R'<./pass.txt$tr'[a-z]''[A-Z]'<./pass.txt#刪除字符$tr-d[0-9]<filename#刪除所有數(shù)字$tr-d''<filename #刪除所有空格#合并重復(fù)字符$echoaaaabbbbccccddddddd|tr-s"[a-z]"#abcd#字符串的替換$echo123456789|tr'1-9''[A*5]'BCDE#AAAAABCDE$echo123456789|tr'1-9''[A*6]'BCDE#AAAAAABCDtr字符串范圍列表[a-z]:a-z內(nèi)的字符組成的字符串[A-Z]:A-Z內(nèi)的字符組成的字符串[0-9]:數(shù)字串\octal:一個(gè)三位的八進(jìn)制數(shù)[O*n]:表示字符O重復(fù)出現(xiàn)指定次數(shù)n1、tr簡介2、tr語法grepgrep[options]patternfiles-c:只顯示有多少行匹配,而不具體顯示匹配的行-h:不顯示文件名-H:在每個(gè)符合的行前加上符合的文件名稱-i:在字符串比較的時(shí)候忽略大小寫-l:只顯示包含匹配模板的行的文件名清單-L:只顯示不包含匹配模板的行的文件名清單-n:在每一行前面打印該行在文件中的行數(shù)-v:反向檢索,只顯示不匹配的行-w:只顯示完整單詞的匹配-x:只顯示完整行的匹配-q:不顯示任何輸出-C:列出符合行外并列出上下各NUM行,默認(rèn)為2-B:列出符合行外并列出之前的NUM行-A:列出符合行外并列出之后的NUM行-E:擴(kuò)展正則表達(dá)式-r/-R:若是目錄,則遞歸搜索其所有子目錄和文件1、grep語法2、grep參數(shù)3、grep退出狀態(tài)0:成功1:無法找到匹配的pattern2:文件不存在$grep'root'/etc/passwdroot:x:0:0:root:/root:/bin/bash$echo$?0#用戶root1并不存在$grep'root1'/etc/passwd$echo$?1#/etc/passwd1文件并不存在$grep'root'/etc/passwd1grep:/etc/passwd1:Nosuchfileordirectory$echo$?2grep$grepNWfile

#打印出file中所有包含NW的行$grep'^n'file

#打印出以n開頭的行$grep'4$'file

#打印出以4結(jié)尾的行$grep'5\..'file

#打印出第一個(gè)字符是5,后面跟著一個(gè).字符,再后面是任意字符的行$grep'\.5'file

#打印出所有包含.5的行$grep'^[we]'file

#打印出所有以w或e開頭的行$grep'[^0-9]'file

#打印出所有不是以0-9開頭的行$grep'[A-Z][A-Z]'file

#打印出所有前一個(gè)字符是大寫,后跟一個(gè)空格及一個(gè)大寫字母的行$grep'[a-z]\{9\}'file

#打印所有包含至少有9個(gè)連續(xù)小寫字符的字符串的行$grep'\<north'file

#打印所有以north開頭的單詞的行$grep'\<north\>'file

#打印所有包含單詞north的行$grep'^n\w*'file

#第一個(gè)字符是n,后面是任意字母或者數(shù)字$egrep'NW|EA'file

#打印所有包含NW或EA的行?;騡rep-E$grep'NW\|EA'file

#對于標(biāo)準(zhǔn)grep,若在擴(kuò)展元字符前面加\,grep會自動啟用-E4、greppattern實(shí)例dd用指定大小的塊拷貝一個(gè)文件,并在拷貝的同時(shí)進(jìn)行指定的轉(zhuǎn)換1、dd描述2、dd格式dd-if=-of=...3、dd常用參數(shù)if=輸入文件名:缺省為標(biāo)準(zhǔn)輸入of=輸出文件名:缺省為標(biāo)準(zhǔn)輸出ibs=bytes:一次讀入bytes個(gè)字節(jié),即指定一個(gè)塊大小為bytes個(gè)字節(jié)obs=bytes:一次輸出bytes個(gè)字節(jié),即指定一個(gè)塊大小為bytes個(gè)字節(jié)bs=bytes:同時(shí)設(shè)置讀入/輸出的塊大小為bytes個(gè)字節(jié)skip=blocks:從輸入文件開頭跳過blocks個(gè)塊后再開始復(fù)制count=blocks:僅拷貝blocks個(gè)塊,塊大小等于ibs指定的字節(jié)數(shù)conv=conversion:用指定的參數(shù)轉(zhuǎn)換文件(lcase:大寫轉(zhuǎn)小寫;ucase:小寫轉(zhuǎn)大寫)4、dd備份與恢復(fù)備份并壓縮:ddif=/dev/hdb|gzip>/root/image.gz恢復(fù)壓縮文件:gzip-dc/root/image.gz|ddof=/dev/hdb${}用法取值含義結(jié)果${file#*/}拿掉第一條/及其左邊的字串dir1/dir2/dir3/my.file.txt${file##*/}拿掉最后一條/及其左邊的字串my.file.txt${file#*.}拿掉第一個(gè).及其左邊的字串file.txt${file##*.}拿掉最后一個(gè).及其左邊的字串txt${file%/*}拿掉最后條/及其右邊的字串/dir1/dir2/dir3${file%%/*}拿掉第一條/及其右邊的字串(空值)${file%.*}拿掉最后一個(gè).及其右邊的字串/dir1/dir2/dir3/my.file${file%%.*}拿掉第一個(gè).及其右邊的字串/dir1/dir2/dir3/my${file:0:5}提取最左邊的5個(gè)字符/dir1${file:5:5}提取第5個(gè)字符右邊的連續(xù)5個(gè)字符/dir2假設(shè):file=/dir1/dir2/dir3/my.file.txt1、字符串取值${}用法字符串替換含義結(jié)果${file/dir/path}將第一個(gè)dir提換為path/path1/dir2/dir3/my.file.txt${file//dir/path}將全部dir提換為path/path1/path2/path3/my.file.txt${#file}計(jì)算出變量值的長度27賦值含義var=${str-expr}當(dāng)str未定義時(shí),var=expr;否則var=$strvar=${str:-expr}當(dāng)str未定義或?yàn)榭罩禃r(shí),var=expr;否則var=$strvar=${str+expr}與-正好相反:當(dāng)str未定義時(shí),var=$str;否則var=exprvar=${str:+expr}與:-正好相反:當(dāng)str未定義或?yàn)榭罩禃r(shí),var=$str;否則var=exprvar=${str=expr}當(dāng)str未定義時(shí),var=expr,str=expr;否則str不變,var=$strvar=${str:=expr}當(dāng)str未定義或?yàn)榭罩禃r(shí),var=expr,str=expr;否則str不變,var=$strvar=${str?expr}當(dāng)str未定義時(shí),expr輸出至stderr;否則var=$strvar=${str:?expr}當(dāng)str未定義或?yàn)榭罩禃r(shí),expr輸出至stderr;否則var=$str假設(shè):file=/dir1/dir2/dir3/my.file.txt2、字符串替換3、字符串賦值(())用法a=$((5+3))#加法a=$((5-3))#減法a=$((5*3))#乘法a=$((5/3))#除法a=$((5**3))#冪運(yùn)算a=$((5%3))#

取模2、使用C風(fēng)格的變量處理((a=23)) #給一個(gè)變量賦值((a++)) #變量'a'后加1((a--)) #變量'a'后減1((++a)) #變量'a'預(yù)加1((--a)) #變量'a'預(yù)減1n=1;((--a))&&echo"True"||echo"False"#Falsen=1;((a--))&&echo"True"||echo"False"#True1、算術(shù)擴(kuò)展和賦值求交集、并集、差集1、求文件交集awk'ARGIND==1{g[$1]=1}ARGIND>1&&(g[$1]==ARGIND-1){g[$1]++}END{for(iing){if(g[i]==ARGIND){printi;}}}'f1f2f3...fn2、求文件并集awk'{a[$1]}END{printlength(a)}'f1f2f33、求文件差集awk'ARGIND==1{g[$1]}ARGIND>1&&!($1ing){b[$1]}END{for(iinb){

printi;}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論