【shell筆記>腳本】構(gòu)建基本shell腳本

內(nèi)容

  • 使用多個命令
  • 創(chuàng)建腳本文件
  • 顯示消息
  • 使用變量
  • 輸入輸出重定向
  • 管道
  • 數(shù)學運算
  • 退出腳本

使用多個命令

如果多個命令一起使用,可以放在一行并用分號分隔祝峻。

wsx@wsx-ubuntu:~$ date; who
2017年 07月 26日 星期三 09:53:43 CST
wsx      tty7         2017-07-26 09:48 (:0)

創(chuàng)建腳本文件

在創(chuàng)建腳本文件時,必須在文件的第一行指定要使用的shell猴蹂,格式為:

#!/bin/bash

腳本文件的第一行中#后的驚嘆號會告訴shell使用哪個shell來運行腳本(如果是其他編碼語言腳本退子,像python,第一行類似)宫仗。

其他地方的#用作注釋行。

添加名為test1的腳本文件旁仿,內(nèi)容為:

#!/bin/bash
# This script displays the date and who's logged on
date
who

現(xiàn)在運行腳本藕夫,結(jié)果會是:

wsx@wsx-ubuntu:~/script_learn$ test1
未找到 'test1' 命令,您要輸入的是否是:
 命令 'testr' 來自于包 'python3-testrepository' (main)
 命令 'testr' 來自于包 'python-testrepository' (universe)
 命令 'test' 來自于包 'coreutils' (main)
test1:未找到命令

我們現(xiàn)在需要做的是讓bash shell能夠找到我們的腳本文件枯冈。shell會通過PATH環(huán)境變量來查找命令毅贮,我們可以看看:

wsx@wsx-ubuntu:~/script_learn$ echo $PATH
/home/wsx/Anaconda/bin:/home/wsx/Anoconda/ENTER/bin:/usr/lib/jvm/default-java/bin:/home/wsx/bin:/home/wsx/Anaconda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

很顯然,我們的文件沒有在這些目錄范圍內(nèi)尘奏。要讓shell找到test1腳本滩褥,我們可以采取以下兩種做法之一:

  • 將shell腳本文件所處的目錄添加到PATH環(huán)境變量中;
  • 在提示符中用絕對路徑或相對路徑來引用shell腳本文件炫加。

第二種方法比較簡單瑰煎,我們在這里試試:

wsx@wsx-ubuntu:~/script_learn$ ./test1
bash: ./test1: 權(quán)限不夠
wsx@wsx-ubuntu:~/script_learn$ ll test1 # 發(fā)現(xiàn)權(quán)限不夠铺然,查看文件的權(quán)限
-rw-rw-r-- 1 wsx wsx 73 7月  26 10:03 test1
wsx@wsx-ubuntu:~/script_learn$ chmod u+x test1 # 修改權(quán)限,添加可執(zhí)行屬性
wsx@wsx-ubuntu:~/script_learn$ ./test1 # 成功運行腳本
2017年 07月 26日 星期三 10:09:23 CST
wsx      tty7         2017-07-26 09:48 (:0)

顯示消息

echo命令后面加上一個字符串酒甸,就能顯示出這個文本字符串魄健。這種方式可以添加自己的文本消息來告訴腳本用戶腳本正在做什么。

wsx@wsx-ubuntu:~/script_learn$ echo This is a test
This is a test

如果文本本身帶有字符串插勤,我們需要用單引號或雙引號來劃定文本字符串沽瘦。

wsx@wsx-ubuntu:~/script_learn$ echo "Let's see if this'll work"
Let's see if this'll work

我們修改下之前的test1文件岁忘,增加消息顯示:

#!/bin/bash
# This script displays the date and who's logged on
echo The time and date are:
date
echo "Let's see who's logged into the system"
who

運行:

wsx@wsx-ubuntu:~/script_learn$ ./test1
The time and date are:
2017年 07月 26日 星期三 10:17:59 CST
Let's see who's logged into the system
wsx      tty7         2017-07-26 09:48 (:0)

如果想把文本字符串和命令輸出顯示在同一行中笼恰,可以用echo語句的-n參數(shù)。需要在字符串的兩側(cè)加上引號,并且保證字符串尾部有一個空格(不然字符串和命令輸出就粘連到一起了)卤橄。

#!/bin/bash
# This script displays the date and who's logged on
echo -n "The time and date are: " 
date
echo  "Let's see who's logged into the system: " 
who

# 運行結(jié)果輸出
wsx@wsx-ubuntu:~/script_learn$ ./test1
The time and date are: 2017年 07月 26日 星期三 10:24:04 CST
Let's see who's logged into the system: 
wsx      tty7         2017-07-26 09:48 (:0)

使用變量

變量允許我們臨時性地將信息存儲在shell腳本中,以便和腳本中的其他命令一起使用臂外。

環(huán)境變量

shell維護著一組環(huán)境變量窟扑,用來記錄特定的系統(tǒng)信息。比如系統(tǒng)的名稱漏健、登錄到系統(tǒng)上的用戶名嚎货、用戶的系統(tǒng)ID(也稱為UID)、用戶默認主目錄以及shell查找程序的搜索路徑蔫浆。

使用set命令顯示一份完整的當前環(huán)境變量列表殖属。envprintenv命令都可以顯示全局變量。(這些命令輸出結(jié)果比較多瓦盛,不展示了洗显。之前關(guān)于環(huán)境變量的筆記有比較詳細的描述。)

在環(huán)境變量名稱之前加上美元符可以使用這些環(huán)境變量原环。

wsx@wsx-ubuntu:~/script_learn$ cat test2
#! /bin/bash
# display user information from the system
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME
wsx@wsx-ubuntu:~/script_learn$ chmod u+x test2
wsx@wsx-ubuntu:~/script_learn$ ./test2
User info for userid: wsx
UID: 1000
HOME: /home/wsx

可以想象的到挠唆,如果我們想要使用實際的美元符而不是引用變量,肯定會出問題嘱吗。這時候我們需要在美元符前面加上\進行轉(zhuǎn)義玄组,以顯示美元符本身。

用戶變量

使用等號將值賦給用戶變量谒麦。注意俄讹,在變量、等號和值之間不能出現(xiàn)空格绕德!這個是初學者常見的一個問題颅悉,本人也非常不太適應(yīng)這個。因為在其他語言中不區(qū)分等號兩邊的空格迁匠,相信接觸過其他腳本的朋友們肯定有習慣打空格使代碼美觀的剩瓶,這在bash shell中是萬萬行不通滴驹溃。

一個使用的例子:

wsx@wsx-ubuntu:~/script_learn$ cat test3
#!/bin/bash
# testing variables
days=10
guest="Katie"
echo "$guest checked in $days days ago"
days=5
guest="Jessica"
echo "$guest checked in $days days ago"
wsx@wsx-ubuntu:~/script_learn$ chmod u+x test3
wsx@wsx-ubuntu:~/script_learn$ ./test3
Katie checked in 10 days ago
Jessica checked in 5 days ago

變量每次被引用時,都會輸出當前賦給它的值延曙。重要的是要記住豌鹤,引用一個變量值時需要使用美元符,而引用變量來對其進行賦值時則不需要使用美元符枝缔。

命令替換

shell腳本最有用的特性之一就是可以從命令輸出中提取信息布疙,并將其賦給變量。

有兩種方法可以將命令輸出賦給變量:

  • 反引號字符(`)
  • $()格式
要么用一對反引號把整個命令行命令圍起來:
testing=`date`
要么使用$()格式
testing=$(date)

下面是一個例子愿卸,在腳本中通過命令替換獲得當前日期并用它來生成唯一文件名:

wsx@wsx-ubuntu:~/script_learn$ cat test4
#!/bin/bash
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d)
ls /usr/bin -al > log.$today

wsx@wsx-ubuntu:~/script_learn$ chmod u+x test4
wsx@wsx-ubuntu:~/script_learn$ ./test4

重定向輸入和輸出

通過幾個操作符進行重定向灵临,我們可以將命令的結(jié)果輸出到另外的位置(文件)。當然趴荸,重定向可以用于輸入儒溉。

輸出重定向

最基本的操作符是>。比如我們想要輸出命令結(jié)果到一個指定文件:

wsx@wsx-ubuntu:~/script_learn$ date > test6
wsx@wsx-ubuntu:~/script_learn$ ls -l test6
-rw-rw-r-- 1 wsx wsx 43 7月  26 16:42 test6
wsx@wsx-ubuntu:~/script_learn$ cat test6
2017年 07月 26日 星期三 16:42:34 CST

如果想要將命令的輸出追加到已有文件中发钝,需要用雙大于號(>>)來追加數(shù)據(jù)顿涣。

輸入重定向

輸入重定向和輸出重定向正好相反。輸入重定向?qū)⑽募膬?nèi)容重定向到命令酝豪,而非將命令的輸出重定向到文件涛碑。

使用的符號是小于號(<)。

一種簡單的記憶方法是:在命令行上孵淘,命令總是在左側(cè)蒲障,而重定向符號“指向”數(shù)據(jù)流動的方向。小于號說明數(shù)據(jù)正在從輸入文件流向命令瘫证。

比如用wc命令檢查文本的行數(shù)揉阎、詞數(shù)和字節(jié)數(shù)。

wsx@wsx-ubuntu:~/script_learn$ wc < test6
 1  6 43

另一種輸入重定向的方法是內(nèi)聯(lián)輸入重定向痛悯。它無需使用文件進行重定向余黎,只需要在命令行中指定用于輸入重定向的數(shù)據(jù)即可。它使用的符號是遠小于號(<<)载萌,除了這個符號惧财,我們還需要指定一個文本標記用來劃分輸入數(shù)據(jù)的開始和結(jié)尾。任何字符串都可以作為文本標記扭仁,但在數(shù)據(jù)的開始和結(jié)尾文本標記必須一致垮衷。

wsx@wsx-ubuntu:~/script_learn$ wc << EOF
> test string1
> test string2
> test string3
> EOF
 3  6 39

它的形式為:

command << marker
data
marker

管道

有時候需要將一個命令的輸出作為另一個命令的輸入。通過|符號分隔命令即可實現(xiàn)管道乖坠。

比如我想查看某個文件(test1)的前兩行并進行排序搀突,操作如下:

wsx@wsx-ubuntu:~/script_learn$ cat test1
#!/bin/bash
# This script displays the date and who's logged on
echo -n "The time and date are: " 
date
echo  "Let's see who's logged into the system: " 
who
wsx@wsx-ubuntu:~/script_learn$ cat test1 | head -2 | sort
#!/bin/bash
# This script displays the date and who's logged on

管道的強大之處在于可以根據(jù)自己的需求靈活地組合和使用各種linux命令工具。這里只是一個簡單的例子熊泵,要熟練掌握少不了平時多多研究和練習仰迁。

執(zhí)行數(shù)學運算

對shell腳本來說甸昏,執(zhí)行數(shù)學運算非常麻煩。有兩種實現(xiàn)方式徐许。

expr命令

expr命令允許在命令行上處理數(shù)學表達式施蜜,但是特別笨拙。(Bourne shell中)

wsx@wsx-ubuntu:~/script_learn$ exrpr 1 + 5
未找到 'exrpr' 命令雌隅,您要輸入的是否是:
 命令 'expr' 來自于包 'coreutils' (main)
exrpr:未找到命令

看到?jīng)]有翻默,那算了。它基本涉及的操作跟我們使用的其他語言是一致的恰起。但是有些問題需要處理修械,像*是通配符,在運算是是做乘號處理的检盼,需要進行轉(zhuǎn)義肯污。

使用方括號

bash shell提供了一種更簡單的方法來執(zhí)行數(shù)學表達式。在bash中梯皿,在將一個數(shù)學運算結(jié)果賦給某個變量時仇箱,可以用美元符和方括號($[operator])將數(shù)學表達式圍起來县恕。

wsx@wsx-ubuntu:~/script_learn$ var1=$[1+5]
wsx@wsx-ubuntu:~/script_learn$ echo $var1
6
wsx@wsx-ubuntu:~/script_learn$ var2=$[$var1+2]
wsx@wsx-ubuntu:~/script_learn$ echo $var2
8

這種方式不僅方便东羹,而且因為在方括號內(nèi),不會讓shell誤解乘號或其他符號忠烛。

但bash shell計算有一個主要限制:它只支持整數(shù)運算属提!

浮點解決方案

最常見的方案是用內(nèi)建的bash計算器。它實際上是一門編程語言美尸,它允許在命令行中輸入浮點表達式冤议,然后解釋并計算該表達式,最后返回結(jié)果师坎。bash計算器能夠識別:

  • 數(shù)字(整數(shù)和浮點數(shù))
  • 變量(簡單變量和數(shù)組)
  • 注釋(/* */開始的行)
  • 表達式
  • 編程語句
  • 函數(shù)
wsx@wsx-ubuntu:~/script_learn$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
12 * 5.4
64.8
3.156 * (3 + 5)
25.248
quit

在腳本中使用bc

可以用命令替換運行bc命令恕酸,并將輸出賦給一個變量】杪基本格式如下:

variable=$(echo "options; expression" | bc)

options設(shè)置變量蕊温,expression參數(shù)定義了通過bc執(zhí)行的數(shù)學表達式。

看一個簡單實例:

wsx@wsx-ubuntu:~/script_learn$ cat test9
#!/bin/bash
var1=$(echo "scale=4; 3.44/5" | bc)
echo The answer is $var1
wsx@wsx-ubuntu:~/script_learn$ chmod u+x test9
wsx@wsx-ubuntu:~/script_learn$ ./test9
The answer is .6880

這個例子將scale變量設(shè)置為四位小數(shù)遏乔,并在expression部分指定了特定的運算义矛。

這個方法適用于較短的運算,但有時我們會涉及更多的數(shù)字盟萨。如果需要進行大量運算凉翻,在一個命令行中列出多個表達式就會有點麻煩。

這里有一個解決方法:使用內(nèi)聯(lián)輸入重定向捻激,將一個文件重定向到bc命令來處理制轰。格式為:

variable=$(bc << EOF
options
statements
expressions
EOF)

EOF文本字符串標識了內(nèi)聯(lián)重定向數(shù)據(jù)的起始前计。注意,仍然需要命令替換符號將bc命令的輸出賦給變量垃杖。

下面是一個例子:

wsx@wsx-ubuntu:~/script_learn$ cat test10
#!/bin/bash

var1=10.46
var2=43.67
var3=33.2
var4=71

var5=$(bc <<EOF
scale=4
a1 = ( $var1 * $var2)
b1 = ( $var3 * $var4)
a1 + b1
EOF
)

echo The final answer for this mess is $var5
wsx@wsx-ubuntu:~/script_learn$ chmod u+x test10
wsx@wsx-ubuntu:~/script_learn$ ./test10
The final answer for this mess is 2813.9882

在普通的shell腳本中残炮,數(shù)字默認當做字符串處理。這也是為什么我們腳本處理計算麻煩和我們需要特定的工具和方法來進行處理缩滨。一定要注意區(qū)分势就。

退出腳本

前面運行的腳本都是命令執(zhí)行完成,腳本自動結(jié)束脉漏。其實我們可以用更為優(yōu)雅的方式告訴shell命令運行完成苞冯,因為每個命令都使用退出狀態(tài)碼(exit status),它是一個0-255的整數(shù)值侧巨,我們可以捕獲這個值并在腳本中使用舅锄。

Linux提供了一個專門的變量$?來保存上個已執(zhí)行命令的退出狀態(tài)碼。

wsx@wsx-ubuntu:~/script_learn$ date
2017年 07月 27日 星期四 10:44:18 CST
wsx@wsx-ubuntu:~/script_learn$ echo $?
0

按照慣例司忱,一個成功結(jié)束的命令的退出狀態(tài)碼是0皇忿。如果有錯誤,則顯示一個正數(shù)值坦仍。

Linux錯誤退出狀態(tài)碼沒有什么標準鳍烁,但有一些參考:

狀態(tài)碼 描述
0 命令成功結(jié)束
1 一般性未知錯誤
2 不適合的shell命令
126 命令不可執(zhí)行
127 沒找到命令
128 無效的退出參數(shù)
128+x 與Linux信號x相關(guān)的嚴重錯誤
130 通過Ctrl+C終止的命令
255 正常范圍之外的退出狀態(tài)碼
wsx@wsx-ubuntu:~/script_learn$ asfg
未找到 'asfg' 命令,您要輸入的是否是:
 命令 'asdfg' 來自于包 'aoeui' (universe)
asfg:未找到命令
wsx@wsx-ubuntu:~/script_learn$ echo $?
127

exit命令

默認繁扎,shell腳本會以腳本最后的一個命令的退出狀態(tài)碼退出幔荒。

但是我們可以改變這種默認行為,返回自己的退出狀態(tài)碼梳玫。exit命令允許在腳本結(jié)束時指定一個狀態(tài)退出碼爹梁。

wsx@wsx-ubuntu:~/script_learn$ cat test13
#!/bin/bash
# testing the exit status
var1=10
var2=30
var3=$[$var1 + $var2]
echo The answer is $var3
exit 5

wsx@wsx-ubuntu:~/script_learn$ chmod u+x test13
wsx@wsx-ubuntu:~/script_learn$ ./test13
The answer is 40
wsx@wsx-ubuntu:~/script_learn$ echo $?
5

注意最大255,如果大于它提澎,得到的是求模的結(jié)果(余數(shù))姚垃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盼忌,隨后出現(xiàn)的幾起案子积糯,更是在濱河造成了極大的恐慌,老刑警劉巖碴犬,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件絮宁,死亡現(xiàn)場離奇詭異,居然都是意外死亡服协,警方通過查閱死者的電腦和手機绍昂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窘游,你說我怎么就攤上這事唠椭。” “怎么了忍饰?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵贪嫂,是天一觀的道長。 經(jīng)常有香客問我艾蓝,道長力崇,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任赢织,我火速辦了婚禮亮靴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘于置。我一直安慰自己茧吊,他們只是感情好,可當我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布八毯。 她就那樣靜靜地躺著搓侄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪话速。 梳的紋絲不亂的頭發(fā)上讶踪,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機與錄音尿孔,去河邊找鬼俊柔。 笑死筹麸,一個胖子當著我的面吹牛活合,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播物赶,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼白指,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了酵紫?” 一聲冷哼從身側(cè)響起告嘲,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奖地,沒想到半個月后橄唬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡参歹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年仰楚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡僧界,死狀恐怖侨嘀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情捂襟,我是刑警寧澤咬腕,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站葬荷,受9級特大地震影響涨共,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜宠漩,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一煞赢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧哄孤,春花似錦照筑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至晨逝,卻和暖如春蛾默,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背捉貌。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工支鸡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人趁窃。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓牧挣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親醒陆。 傳聞我的和親對象是個殘疾皇子瀑构,可洞房花燭夜當晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Ubuntu的發(fā)音 Ubuntu澡刹,源于非洲祖魯人和科薩人的語言呻征,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 99,271評論 9 467
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,168評論 2 33
  • 建立一個腳本 Linux中有好多中不同的shell罢浇,但是通常我們使用bash (bourne again shel...
    某人在閱讀 2,012評論 0 0
  • 基礎(chǔ) 頭文件 #!/bin/bash 或者#!/bin/sh #!約定的標記陆赋,如IOS的Import 執(zhí)行文件時需...
    ZMJun閱讀 1,232評論 1 2
  • 好多人說:身體和靈魂必須要有一個在路上边篮。我的身體已經(jīng)在路上了,靈魂卻不知道飄哪去了奏甫。累戈轿,困,堵車阵子,坐車都坐得腰酸背...
    當額咧閱讀 75評論 0 0