Shell 腳本語言是實現 Linux/UNIX 系統管理及自動化運維所必備的重要工具, Linux/UNIX 系統的底層及基礎應用軟件的核心大都涉及 Shell 腳本的內容。每個合格 的Linux 系統管理員或運維工程師,都須要可以熟練地編寫 Shell 腳本語言,並可以閱讀系統及各種軟件附帶的 Shell 腳本內容。只有這樣才能提高運維人員的工做效率,適 應曰益複雜的工做環境,減小沒必要要的重複工做,從而爲我的的職場發展奠基較好的基礎php
Shell 是一個命令解釋器,它在操做系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操做系統,並處理各類各樣的操做系統的輸出結果,輸出屏幕返回給用戶。
html
這種對話方式能夠是:前端
[root@mico ~]# echo "hello" hello [root@mico ~]# pwd /root [root@mico ~]#
定義:指用專用的編譯器,針對特定的操做平臺(操做系統)將某種高級語言源代碼一次性翻譯成可被硬件平臺直接運行的二進制機器碼(具備操做數,指令、及相應的格式),這個過程叫作編譯(./configure make makeinstall );編譯好的可執行性文件(.exe),可在相對應的平臺上運行(移植性差,但運行效率高)。典型的編譯型語言有, C語言、C++等。另外,Java語言是一門很特殊的語言,Java程序須要進行編譯步驟,但並不會生成特定平臺的二進制機器碼,它編譯後生成的是一種與平臺無關的字節碼文件(*.class)(移植性好的緣由),這種字節碼天然不能被平臺直接執行,運行時須要由解釋器解釋成相應平臺的二進制機器碼文件;大多數人認爲Java是一種編譯型語言,但咱們說Java便是編譯型語言,也是解釋型語言也並無錯。
定義:指用專門解釋器對源程序逐行解釋成特定平臺的機器碼並當即執行的語言;至關於把編譯型語言的編譯連接過程混到一塊兒同時完成的。解釋型語言執行效率較低,且不能脫離解釋器運行,但它的跨平臺型比較容易,只需提供特定解釋器便可。常見的解釋型語言有, Python(同時是腳本語言)與Ruby等。
定義:爲了縮短傳統的編寫-編譯-連接-運行(edit-compile-link-run)過程而建立的計算機編程語言。 特色:程序代碼便是最終的執行文件,只是這個過程須要解釋器的參與,因此說腳本語言與解釋型語言有很大的聯繫。腳本語言一般是被解釋執行的,並且程序是文本文件。
典型的腳本語言有,JavaScript,Python,shell等。java
shell 腳本的優點在於處理操做系統底層的業務 (linux 系統內部的應用都是 shell 腳本完成)由於有大量的 linux 系統命令爲它作支撐。2000 多個命令都是 shell 腳本編程的有力支撐,特別是grep、awk、sed 等。例如:一鍵軟件安裝、優化、監控報警腳本,常規的業務應用,shell 開發更簡單快速,符合運維的簡單、易用、高效原則。PHP、Python 優點在於開發運維工具以及 web 界面的管理工具,web 業務的開發等。處理一鍵軟件安裝、優化,報警腳本。常規業務的應用等 php/python 也是可以作到的。可是開發效率和複雜比用 shell 就差不少了。python
[root@mico ~]# cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) [root@mico ~]# uname -r 3.10.0-862.11.6.el7.x86_64 [root@mico ~]# getenforce Disabled [root@mico ~]# systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: inactive (dead) Docs: man:firewalld(1) [root@mico ~]#
[root@mico ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh [root@mico ~]#
[root@mico ~]# echo $SHELL /bin/bash
[root@VM_42_34_centos /]# head -1 /etc/init.d/network #! /bin/bash [root@VM_42_34_centos /]# head -1 /etc/init.d/netconsole #!/bin/bash
[root@mico ~]# bash -version GNU bash, 版本 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. 許可證 GPLv3+: GNU GPL 許可證版本3或者更高 <http://gnu.org/licenses/gpl.html> 這是自由軟件,您能夠自由地更改和從新發布。 在法律容許的範圍內沒有擔保.
使用 命令 env x='() { :;}; echo be careful' bash -c "echo this is a test"
若是返回結果爲一行,則爲正常,linux
[root@mico ~]# env x='() { :;}; echo be careful' bash -c "echo this is a test" this is a test #解決辦法 升級當前的bash版本 yum install update bash
早期的bash和sh稍有不一樣,還包含了csh和ksh的特點,但大多數腳本均可以不加修改地在sh上運行web
[root@VM_42_34_centos ~]# ll /bin/bash -rwxr-xr-x 1 root root 964544 4月 11 2018 /bin/bash [root@VM_42_34_centos ~]# ll /bin/sh lrwxrwxrwx 1 root root 4 8月 10 2018 /bin/sh -> bash
說明:sh爲bash的軟連接,通常狀況下,腳本開頭使用「#!/bin/bash」和"#!/bin/sh"是沒有區別的,但更規範的寫法是在腳本開頭使用「#!/bin/bash」
下面的Shell腳本是系統自帶的軟件啓動腳本的開頭部分面試
[root@mico ~]# ll /bin/sh lrwxrwxrwx 1 root root 4 8月 10 2018 /bin/sh -> bash
[root@mico ~]# ll /bin -d lrwxrwxrwx 1 root root 7 8月 10 2018 /bin -> usr/bin
[root@mico ~]# mkdir -p /server/scripts/ [root@mico ~]# cd /server/scripts/
腳本第一行指出由哪一個程序(解釋器)來執行腳本中的內容
#!/bin/bash
或#!/bin/sh
(255個字符之內)shell
注意格式 ↓
其中開頭的"#!"字符又稱爲幻數,在執行bash腳本的時候,內核會根據"#!"後的解釋器來肯定該用那個程序解釋這個腳本中的內容。編程
[root@mico scripts]# head -1 /etc/init.d/* ==> /etc/init.d/functions <== # -*-Shell-script-*- ==> /etc/init.d/netconsole <== #!/bin/bash ==> /etc/init.d/network <== #! /bin/bash ==> /etc/init.d/README <== You are looking for the traditional init scripts in /etc/rc.d/init.d,
使用 .vimrc
文件,將下面的信息添加到 .vimrc
文件中,可以快速的生成開頭的註釋信息
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1,"#!/bin/bash") call setline(2, "##############################################################") call setline(3, "# File Name: ".expand("%")) call setline(4, "# Version: V1.0") call setline(5, "# Author: mico") call setline(6, "# Created Time : ".strftime("%F %T")) call setline(7, "# Description:") call setline(8, "##############################################################") call setline(9, "") endif endfunc
使用後的效果
#!/bin/bash ############################################################## # File Name: scripts_tmp.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-09 10:12:27 # Description: ##############################################################
在Shell腳本中,跟在#
後面的內容表示註釋。註釋部分不會被執行,僅給人看。註釋能夠自成一行,也能夠跟在命令後面,與命令同行。要養成寫註釋的習慣,方便本身與他人。
最好不用中文註釋,由於在不一樣字符集的系統會出現亂碼。(字符集爲zh_CN.UTF-8,爲中文)。
名字要有意義,而且結尾以 .sh
結束(並非必須)
.sh
爲擴展名~/.vimrc
文件自動添加。[ ]
、' '
、" "
等[ ]
兩端要有空格,先輸入[ ]
,退格,輸入 2 個空格,再退格寫。if 條件 ; then 內容;fi
)當 Shell 腳本運行時,會先查找系統環境變量 ENV,該變量指定了環境文件(加載順序一般是 /etc/profile
、~/.bash_profile
、~/.bashrc
、/etc/bashrc
),在加載了上述變量文件後,Shell就開始執行腳本中的內容。
Shell 腳本是從上至下、從左至右依次執行每一行的命令及語句的。即執行完了一個命令後再執行下一個,若是在 Shell 腳本中(即腳本嵌套)
時,就會先執行子腳本的內容,完成後再返回父腳本繼續執行父腳本內後序的命令及語句。
一般狀況下,在執行 Shell 腳本時,會向系統內核請求啓動一個新進程,以便在該進程或只能怪執行腳本的命令以及子Shell 腳本。
(1)sh/bash scripts.sh
當腳本自己沒有可執行權限時使用的方法,或腳本文件開頭沒有指定解釋器時須要使用分方法。
(2)首先chown +x
,而後./scripts.sh
或 .path/scripts.sh
在當前路徑下執行腳本(腳本須要有執行權限),經過絕對路徑或相對路徑直接執行腳本
(3)source scripts.sh
或 . (空格) scripts.sh
這種方法一般是使用 source
或 .
讀入或加載指定的 shell 腳本文件(不須要執行權限),而後依次執行指定 shell 腳本中的全部語句。這些語句將在當前 shell 腳本的進程中運行(其餘幾種模式都會啓動新的進程執行子腳本)。source
或 .
命令的功能是在當前 Shell 中執行 source
或 .
加載並執行的相關腳本文件中的命令及語句,而不是產生一個子 Shell 來執行文件中的命令。
說明:.
或 source
命令的功能相同,都是讀入腳本並執行腳本中的命令。
(4)sh < script-name 或 cat scripts-name|sh 效率低
一樣適用於bash,不過這種用法不常見。
soucre命令
[root@mico ~]# help source |head -2 source: source 文件名 [參數] 在當前 shell 中執行一個文件中的命令。 . (點) [root@mico ~]# help . |head -2 .: . 文件名 [參數] 在當前 shell 中執行一個文件中的命令。
對比:用 source 執行腳本文件,執行過程不另開進程,腳本文件中設定的變量在當前shell中能夠看到;
用 sh/bash 執行腳本文件,是在當前進程另開子進程來執行腳本命令,腳本文件中設定的變量在當前shell中不能看到。
例如
[root@VM_42_34_centos trsky]# echo 'userdir=`pwd`' >> testsource.sh [root@VM_42_34_centos trsky]# cat testsource.sh userdir=`pwd` [root@VM_42_34_centos trsky]# sh testsource.sh [root@VM_42_34_centos trsky]# echo $userdir [root@VM_42_34_centos trsky]# source testsource.sh [root@VM_42_34_centos trsky]# echo $userdir /home/trsky [root@VM_42_34_centos trsky]#
由案例可知,使用 source
或 .
執行的腳本中的變量值會傳遞到當前的 Shell 下,由於使用 source
或 .
執行腳本不會開啓新的進程,而是在統一進程下完成腳本中全部指令的執行。
[root@mico scripts]# sh mico_test.sh Hello World! [root@mico ~]# echo $Mico Mico # sh 新建一個Shell窗口(新建一個進程)執行一個文件中的命令。 [root@mico scripts]# source mico_test.sh Hello World! [root@mico scripts]# echo $mico Hello World!
問 sh test.sh 後 echo $user 返回的結果__空_ ?
[root@oldboy scripts]# cat test.sh #!/bin/bash user=`whoami`
Shell爲弱類型語言,因此在默認狀況下,在Bash Shell中是不會區分變量類型的。但Shell能夠通 declare 顯示定義變量的類型。
變量能夠分爲兩類:環境變量(全局變量)和普通變量(局部變量)
Shell中定義變量名以及爲變量內容賦值要求
變量名通常由字母、數字、下劃線組成,能夠由字母或下劃線開頭
把一個命令的結果做爲變量的內容賦值的方法
ls
使用 env/declare/set/export -p
命令查看系統中的環境變量,這三個命令的的輸出方式稍有不一樣。
[root@mico scripts]# env XDG_SESSION_ID=1 HOSTNAME=mico TERM=linux SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=10.0.0.1 5537 22 SSH_TTY=/dev/pts/0 USER=root ~~~
[root@mico ~]# echo $LANG zh_CN.UTF-8
設置環境變量
export
和 declare
[root@VM_42_34_centos ~]# cat /etc/profile|grep Mico export Mico='mico' [root@VM_42_34_centos ~]# source /etc/profile [root@VM_42_34_centos ~]# echo $MIco [root@VM_42_34_centos ~]# echo $Mico mico [root@VM_42_34_centos ~]# env|grep Mico Mico=mico [root@VM_42_34_centos ~]#
# 用戶的環境變量設置,比較常見的是用戶家目錄下的.bashrc 和 .bash_profile [root@mico ~]# ls /root/.bashrc /root/.bashrc [root@mico ~]# ls /root/.bash_profile /root/.bash_profile [root@mico ~]#
/etc/profile /etc/bashrc /etc/profile.d/
若是要在登錄後初始化或顯示加載內容,則將腳本文件放在/etc/profile.d/下便可(無需執行權限)
/etc/motd
裏增長提示的字符串[root@mico ~]# vim /etc/motd [root@mico ~]# cat /etc/motd Welcome to Linux.
/etc/profile.d/
目錄下添加腳本[root@mico profile.d]# cat /etc/profile.d/mico.sh #!/bin/bash ############################################################## # File Name: /etc/profile.d/mico.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-01 10:00:06 # Description: ############################################################## echo "Hello, you are studing Linux"
登陸後出現
Connection established. To escape to local shell, press 'Ctrl+Alt+]'. Welcome to Linux. Hello, you are studing Linux [root@mico ~]#
#常見的系統環境變量 $HOME:用戶登陸時進入的目錄 $UID:當前用戶的UID(用戶標識),至關於 id-u $PWD:當前工做目錄的絕對路徑名 $SHELL:當前Shell $USER:當前yonghu ... 打印或刪除環境變量 #打印環境 printf "$Home\n" echo $PWD
#刪除環境變量 unset PWD
本地變量在用戶當前的Shell生存期的腳本中使用。例如,本地變量OLDBOY取值爲bingbing,這個值在用戶當前Shell生存期中有意義。若是在Shell中啓動另外一個進程或退出,本地變量值將無效
變量名=value //解釋變量名 變量名='value' //不解釋變量名 變量名="value" //解釋變量名
[root@mico ~]# a=1 [root@mico ~]# b='2' [root@mico ~]# c="3" [root@mico ~]# echo "$a" 1 [root@mico ~]# echo "$b" 2 [root@mico ~]# echo "${c}"
提示:$變量名錶示輸出變量,能夠用$c和${c}兩種用法
【小結】連續普通字符串內容賦值給變量,無論用什麼引號或者不用引號,它的內容是什麼,打印變量就輸出什麼
[root@mico ~]# help export export: export [-fn] [名稱[=值] ...] 或 export -p 爲 shell 變量設定導出屬性。
標記每一個 NAME 名稱爲自動導出到後續命令執行的環境。若是提供了 VALUE
則導出前將 VALUE 做爲賦值。
定義變量
[root@mico scripts]# CSLN=mico [root@mico scripts]# export CSLN1=1 # 當前窗口查看 [root@mico scripts]# echo $CSLN mico [root@mico scripts]# echo $CSLN1 1 # 編寫測試腳本 [root@mico scripts]# vim quanju.sh #!/bin/bash echo $CSLN echo $CSLN1 # 使用sh執行 [root@mico scripts]# sh quanju.sh 1 # 使用source 執行 [root@mico scripts]# source quanju.sh mico 1
① /etc/profile
② ~/.bash_profile
③ ~/.bashrc
④ /etc/bashrc
1) 經過系統用戶登錄後默認運行的shell
2) 非登陸交互式運行Shell
3) 執行腳本運行非交互式Shell
文件讀取過程示意圖
驗證四文件讀取順序的方法
sed -i '1a echo "$(date +%T-%s) /etc/profile1" >>/tmp/mico' /etc/profile sed -i '$a echo "$(date +%T-%s) /etc/profile2" >>/tmp/mico' /etc/profile sed -i '1a echo "$(date +%T-%s) /etc/bashrc1" >>/tmp/mico' /etc/bashrc sed -i '$a echo "$(date +%T-%s) /etc/bashrc2" >>/tmp/mico' /etc/bashrc sed -i '1a echo "$(date +%T-%s) ~/.bashrc1" >>/tmp/mico' ~/.bashrc sed -i '$a echo "$(date +%T-%s) ~/.bashrc2" >>/tmp/mico' ~/.bashrc sed -i '1a echo "$(date +%T-%s) ~/.bash_profile1" >>/tmp/mico' ~/.bash_profile sed -i '$a echo "$(date +%T-%s) ~/.bash_profile2" >>/tmp/mico' ~/.bash_profile
環境變量通常是指用export內置命令導出的變量,用戶定義shell的運行環境。保證shell命令的正確執行。Shell經過環境變量來肯定登陸用戶名、命令路徑、終端類型、登陸目錄等。若是須要永久保存環境變量,可在用戶家目錄下的.bash_profile或.bashrc(非用戶登陸模式特有,例如遠程登陸SSH)文件中,或者全局配置/etc/bashrc(非用戶登陸模式特有,如遠程SSH)或/etc/profile文件中定義。在將環境變量放入上述的文件以後,每次用戶登陸時這些變量將被初始化。
[root@mico ~]# name=vicodona [root@mico ~]# name2='mico' [root@mico ~]# name3="you are my heart" [root@mico ~]# echo $name vicodona [root@mico ~]# echo $name2 mico [root@mico ~]# echo $name3 you are my heart [root@mico ~]# name4='mi co' [root@mico ~]# echo $name4 mi co [root@mico ~]# name5="mi co" [root@mico ~]# echo $name5 mi co [root@mico ~]# name6="mico $PWD" [root@mico ~]# echo $name6 mico /root [root@mico ~]# name6='mi co $PWD' [root@mico ~]# echo $name6 mi co $PWD [root@mico ~]# name7="mico $PWD" [root@mico ~]# echo $name7 mico /root
a.MicoAge=22 b.NETWORKING=yes
a.NFSD_MODULE="no load" b.MyName="Oldboy is a handsome boy."
a.OLDBOY_NAME='OLDBOY'
[root@mico scripts]# time=`date` [root@mico scripts]# echo $time 2017年 12月 05日 星期二 09:02:06 CST [root@mico scripts]# file=`ls` [root@mico scripts]# echo $file mico_test.sh panduan.sh quanju.sh yhk.sh
打印變量的時候防止出現「金庸新著」的問題
[root@mico ~]# time=`date` [root@mico ~]# echo $time 2019年 07月 18日 星期四 17:47:23 CST [root@mico ~]# echo ${time}_day 2019年 07月 18日 星期四 17:47:23 CST_day [root@mico ~]# echo $time-day 2019年 07月 18日 星期四 17:47:23 CST-day
# 使用腳本測試 [root@mico ~]# vim variable.sh #!/bin/bash time=`date` echo $timeday echo ${time}day [root@mico ~]# sh variable.sh 2019年 07月 18日 星期四 17:49:51 CSTday
名稱 | 解釋 |
---|---|
單引號 | 所見即所得,即輸出時會將單引號內的全部內容都原樣輸出,或者描述爲單引號裏面看到的是什麼就會輸出什麼;這稱爲強引用 |
雙引號(默認) | 輸出雙引號內的全部內容;若是內容中有命令、變量、特殊字符等,會先把變量、命令、轉義字符解析出結果,而後再輸出最終內容,推薦使用,稱爲弱引用 |
無引號 | 賦值時,若是變量內容中有空格,則會形成賦值不完整。而在輸出內容時,會將含有空格的字符串視爲一個總體來輸出;若是內容中有命令、變量等,則會先把變量、命令解析出結果,而後輸出最終內容;若是字符串中帶有空格等特殊字符,則有可能沒法完整的輸出,所以須要改加雙引號 |
反引號 | 通常用於引用命令,執行的時候命令會被執行,至關於`$()`,賦值和輸出都要用 命令引發來 |
示例:
MicoAge=22 #<==每一個單詞的首字母大寫的寫法 mico_age=22 #<==單詞之間用"_"的寫法 micoAgeSex=man #<==駝峯語法:首個單詞的首字母小寫,其他單詞首字母大寫 MICOAGE=22 #<==單詞全大寫的寫法
經常使用的特殊位置參數說明
位置變量 | 做用說明 |
---|---|
$0 | 獲取當前執行的shell腳本的文件名,若是執行腳本帶路徑那麼就包括腳本路徑。 |
$n | 獲取當前執行的shell腳本的第n個參數值,n=1..9,當n爲0時表示腳本的文件名,若是n大於9用大括號括起來{10},參數以空格隔開。 |
$# | 獲取當前執行的shell腳本後面接的參數的總個數 |
$* | 獲取當前shell的全部傳參的參數,不加引號同$@;若是給$加上雙引號,例如: 「$」,則表示將全部的參數視爲單個字符串,至關於「112$3」。 |
$@ | 獲取當前shell的全部傳參的參數,不加引號同$*;若是給$@加上雙引號,例如: 「$@」,則表示將全部參數視爲不一樣的獨立字符串,至關於「$1」 「$2」 「$3」 「……」,這是將參數傳遞給其餘程序的最佳方式,由於他會保留全部內嵌在每一個參數裏的任何空白。 |
當$*
和$@
都加雙引號時,二者有區別,都不加雙引號時,二者無區別。
舉例說:
腳本名稱叫 test.sh 入參三個: 1 2 3
運行 test.sh 1 2 3後
$* 爲 "1 2 3"(一塊兒被引號包住)
$@ 爲 "1" "2" "3"(分別被包住)
[root@mico ~]# vim parameter.sh #!/bin/bash echo $0 echo "第一個參數:" $1 echo "第二個參數:" $2 echo "第11個參數:" ${11} [root@mico ~]# sh parameter.sh parameter.sh 第一個參數: 第二個參數: 第11個參數: [root@mico ~]# [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一個參數: 1 第二個參數: 2 第11個參數: 11 [root@mico ~]#
[root@mico ~]# cat parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## echo $0 echo "第一個參數:" $1 echo "第二個參數:" $2 echo "第10個參數:" ${10} echo "第11個參數:" ${11} echo "參數個數:" $# [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一個參數: 1 第二個參數: 2 第10個參數: 10 第11個參數: 11 參數個數: 11
[root@mico ~]# vim parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## echo $0 echo "第一個參數:" $1 echo "第二個參數:" $2 echo "第10個參數:" ${10} echo "第11個參數:" ${11} echo "參數個數:" $# echo "參數:"$* [root@mico ~]# sh parameter.sh 1 2 3 4 5 6 7 8 9 10 11 parameter.sh 第一個參數: 1 第二個參數: 2 第10個參數: 10 第11個參數: 11 參數個數: 11 參數:1 2 3 4 5 6 7 8 9 10 11
$*
與$@
對比實踐[root@mico scripts]# set -- "I am" handsome boy.. [root@mico scripts]# echo $1 I am [root@mico scripts]# echo $2 handsome [root@mico scripts]# echo $3 boy.. [root@mico scripts]# echo $* I am handsome boy.. [root@mico scripts]# echo $@ I am handsome boy.. [root@mico scripts]# for i in $*;do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in $@;do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in "$@";do echo $i ;done I am handsome boy.. [root@mico scripts]# for i in "$*";do echo $i ;done I am handsome boy..
Shell進程的特殊狀態變量說明
位置變量 | 做用說明 |
---|---|
$? | 獲取執行上一個指令的執行狀態返回值(0爲成功,非零爲失敗),這個變量最經常使用 |
$$ | 獲取當前執行的Shell腳本的進程號(PID),這個變量不經常使用,瞭解便可 |
$! | 獲取上一個在後臺工做的進程的進程號(PID),這個變量不經常使用,瞭解便可 |
$_ | 獲取在此以前執行的命令或腳本的最後一個參數,這個變量不經常使用,瞭解便可 |
進程參數實踐
[root@mico scripts]# echo $? 0 [root@mico scripts]# echo $$ 1368 [root@mico scripts]# echo $! [root@mico scripts]# echo $_ Echo
Bash Shell常見的內部命令:echo
、eval
、exec
、export
、read
、shift
參數 | 參數說明 |
---|---|
-n | 不要追加換行 |
-e | 啓用下列反斜槓轉義的解釋 |
-E | 顯式地抑制對於反斜槓轉義的解釋 |
`echo' 對下列反斜槓字符進行轉義:
\n
:換行\r
:回車\t
:橫向製表符\b
:退格\v
:縱向製表符\c
:抑制更多的輸出在命令行中使用
[root@mico scripts]# read 132 [root@mico scripts]# echo $REPLY 132 [root@mico scripts]# read mico 456 [root@mico scripts]# echo $mico 456 [root@mico scripts]# echo $REPLY 132
在腳本中使用
[root@mico scripts]# vim mico_test.sh #!/bin/bash read -p '請輸入:' mico echo $mico 執行結果 [root@mico scripts]# sh mico_test.sh 請輸入:mico_znix mico_znix
[root@mico scripts]# read --help -bash: read: --: 無效選項 read: 用法:read [-ers] [-a 數組] [-d 分隔符] [-i 緩衝區文字] [-n 讀取字符數] [-N 讀取字符數] [-p 提示符] [-t 超時] [-u 文件描述符] [-s不顯示終端的任何輸入] [名稱 ...]
直接賦值方法
[root@mico ~]# cat parameter.sh #!/bin/bash ############################################################## # File Name: parameter.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 17:50:45 # Description: ############################################################## name=MICO age=18 sex=girl hobby=`ls` ethFile=/etc/sysconfig/network-scripts/ifcfg-eth0 echo $hobby ls $ethFile [root@mico ~]# sh parameter.sh default.pass Django-Blog Django-Blog.tar parameter.sh practices scripts server test.sh variable.sh /etc/sysconfig/network-scripts/ifcfg-eth0
交互式設置變量 read
[root@mico ~]# vim keyword.sh #!/bin/bash ############################################################## # File Name: keyword.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 18:42:31 # Description: ############################################################## read -p "請輸入您的學號:" number read -s -p "請輸入姓名:" name echo echo "您的學號:"$number echo "您的姓名:"$name [root@mico ~]# sh keyword.sh 請輸入您的學號:20190729 請輸入姓名: 您的學號:20190729 您的姓名:youka
腳本內容↓
[root@mico ~]# cat keyword.sh #!/bin/bash ############################################################## # File Name: keyword.sh # Version: V1.0 # Author: mico # Created Time : 2019-07-18 18:42:31 # Description: ############################################################## read -p "請輸入您的學號:" number read -s -p "請輸入姓名:" name echo echo "您的學號:"$number echo "您的姓名:"$name [root@mico ~]# vim host_start.sh [root@mico ~]# sh host_start.sh 請輸入主機名:mico 請輸入IP地址的主機位:180 是否重啓服務器:{yes/no}no 請稍後手動重啓系統!
表達式 | 說明 |
---|---|
${parameter} | 返回變量$parameter的內容 |
${#parameter} | 返回變內容的長度(按字符),也適用於特殊變量 |
${parameter:offset} | 在變量${parameter}中,從位置offset以後開始提取子串到結尾 |
${parameter:offset:length} | 在變量${parameter}中,從位置offset以後開始提取長度爲length的子串 |
${parameter#word} | 從變量${parameter}開頭開始刪除最短匹配的word子串 |
${parameter##word} | 從變量${parameter}開頭開始刪除最長匹配的word子串 |
${parameter%word} | 從變量${parameter}結尾開始刪除最短匹配的word子串 |
${parameter%%word} | 從變量${parameter}結尾開始刪除最長匹配的word子串 |
${parameter/pattem/string} | 使用string代替第一個匹配的pattern |
${parameter//pattem/string} | 使用string代替全部匹配的pattern |
[root@mico ~]# export TEMP="Here is Linux" [root@mico ~]# echo ${#TEMP} 13 [root@mico ~]# echo $TEMP|wc -L 13 [root@mico ~]# expr length "$TEMP" 13 [root@mico ~]# echo "$TEMP" Here is Linux [root@mico ~]# echo "$TEMP"|awk '{print length($0)}' 13 [root@mico ~]# time echo ${#TEMP} 13 real 0m0.000s user 0m0.000s sys 0m0.000s [root@mico ~]# time echo $TEMP|wc -L 13 real 0m0.002s user 0m0.000s sys 0m0.002s [root@mico ~]#
[root@mico scripts]# mico=abcABC123ABCabc [root@mico scripts]# echo ${mico#abc} ABC123ABCabc [root@mico scripts]# echo ${mico##abc} ABC123ABCabc [root@mico scripts]# echo ${mico%abc} abcABC123ABC [root@mico scripts]# echo ${mico%%abc} abcABC123ABC [root@mico scripts]# echo ${mico#a*c} ABC123ABCabc [root@mico scripts]# echo ${mico##a*c} [root@mico scripts]# echo ${mico%a*c} abcABC123ABC [root@mico scripts]# echo ${mico%%a*c} [root@mico scripts]# echo ${mico#a*C} 123ABCabc [root@mico scripts]# echo ${mico#a*C} 123ABCabc [root@mico scripts]# echo ${mico##a*C} abc [root@mico scripts]# echo ${mico%a*c} abcABC123ABC [root@mico scripts]# echo ${mico%A*c} abcABC123 [root@mico scripts]# echo ${mico%%A*c} abc
[root@mico scripts]# echo $mico abcABC123ABCabc [root@mico scripts]# echo ${mico/abc/mico} micoABC123ABCabc [root@mico scripts]# echo ${mico//abc/mico} micoABC123ABCmico
echo $(#parameter)
處理最快的緣由是通常狀況下調用外部命令來處理的方式與使用內置操做的速度相差較大。在Shell編程中應該儘可能使用內置命令。
+#
表示從幵頭刪除匹配最短。
##
表示從開頭刪除匹配最長。%
表示從結尾刪除匹配最短。%%
表示從結尾刪除匹配最長。a*c
表示匹配的突符串,*
表示匹配全部,a*c
匹配開頭爲 a、中間爲任意多個字符、結尾爲c的字符串。a*C
表示匹配的字符串,*
表示匹配全部,a*C
匹配開頭爲 a、中間爲任意多個字符、結尾爲C的字符串。表達式 | 說明 |
---|---|
${parameter:-word} | 若是parameter的變量值爲空或未賦值,則會返回word字符串並替代變量的值用途.若是變量未定義,則返回備用的值,防止變量爲空值或因未定義而致使異常 |
${parameter:=word} | 若是parameter的變量值爲空或未賦值,則設置這個變量值爲word,並返回其值。位置變量和特殊變量不適用用途:基本同上一個${parameter>word},但該變量又額外給parameter變量賦值了 |
${parameter:?word} | 若是parameter變量值爲空或未賦值,那麼word字符串將被做爲標準錯誤輸出,不然輸出變量的值。用途:用於捕捉因爲變量未定義而致使的錯誤,並退出程序 |
${parameter:+word} | 若是parameter變量值爲空或未賦值,則什麼都不作,不然word字符串將替代變量的值 |
運算符 | 意義 順序 |
---|---|
++ - - | 增長及減小,可前置/可結尾 |
+ | 一元正號 |
- | 一元負號 |
! | 邏輯與 |
~ | 位的取反 |
* / % | 乘法、除法、取餘數 |
+ | 加法 |
- | 減法 |
<< >> | 向左位移、向右位移 |
< <= > >= | 比較運算符 |
== != | 相等 不相等 |
& | 位的AND |
^ | 位的Exclusive OR |
| | 位的OR |
&& | 邏輯AND |
|| | 邏輯OR |
?: | 條件表達式 |
= += -= *= /= %= &= ^= | 賦值運算符 |
運算操做符與運算命令 | 意義 |
---|---|
(()) | 用於整數運算的經常使用運算符,效率高 |
let | 用於整數運算,相似於"(())" |
expr | 可用於整數運算,但還有不少其餘的額外功能 |
bc | Linux下的一個計算器程序(適合整數以及小數運算) |
$[] | 用於整數的運算 |
awk | awk既能夠用於整數運算,也能夠用於小數運算 |
declare | 定義變量值和屬性,-i參數能夠用於定義整形變量,作運算 |
(())
的操做方法運算操做符與運算命令 | 意義 |
---|---|
((i=i+1)) | 此種書寫方法爲運算後賦值法,即將i+1的運算結構賦值給變量i。注意,不能用"echo((i=i+1))"的形式輸出表達式的值,但能夠用echo$((i=i+1))輸出其值 |
i=$((i+1)) | 能夠在"(())"前加$符,表示將表達式運算後複製給i |
((8>7&&5==5)) | 能夠進行比較操做,還能夠加入邏輯與和邏輯或,用於條件判斷 |
echo $((2+1)) | 須要直接輸出運算表達式的運算結果時,能夠在"(())"前加$符 |
【提示】上面涉及的數字及變量必須爲整數(整型),不能是小數(浮點數)或字符串。後面的bc
和awk
命令能夠用於進行小數(浮點數)運算,但通常用到的較少。
# 形式一 [root@mico scripts]# echo $((1 + 1)) 2 [root@mico scripts]# echo $((2*7-3/6+5)) 19 # 形式二 [root@mico scripts]# ((mico=2*8)) [root@mico scripts]# echo $mico 16 # 形式三 [root@mico scripts]# znix=$((2*7-3/6+5)) [root@mico scripts]# echo $znix 19
示例:
[root@mico scripts]# i=1 [root@mico scripts]# echo $((i++)) 1 [root@mico scripts]# echo $((i++)) 2 [root@mico scripts]# echo $((i--)) 3 [root@mico scripts]# echo $((i--)) 2 [root@mico scripts]# echo $((i--)) 1 [root@mico scripts]# echo $((++i)) 1 [root@mico scripts]# echo $((++i)) 2 [root@mico scripts]# echo $((++i)) 3 [root@mico scripts]# echo $((--i)) 2 [root@mico scripts]# echo $((--i)) 1 [root@mico scripts]# echo $((--i)) 0
記憶方法:++,--
變量a在前,表達式的值爲a,而後a自增或自減,變量a在符號後,表達式值自增或自減,而後a值自增或自減。
[root@mico scripts]# i=1 [root@mico scripts]# i=i+1 [root@mico scripts]# echo $i i+1 [root@mico scripts]# i=1 [root@mico scripts]# let i=i+1 [root@mico scripts]# echo $i 2
[root@mico scripts]# expr 1+1 1+1 [root@mico scripts]# expr 1 + 1 2 [root@mico scripts]# expr 1 * 1 expr: 語法錯誤 [root@mico scripts]# expr 1 \* 1 1
[root@mico scripts]# expr 1 + 1 2 [root@mico scripts]# echo $? 0 [root@mico scripts]# expr -1 + 1 0 [root@mico scripts]# echo $? 1 [root@mico scripts]# expr a + 1 expr: 非整數參數 [root@mico scripts]# echo $? 2 $[]運算符 [root@mico scripts]# echo $[1+2] 3 [root@mico scripts]# echo $[1-2] -1 [root@mico scripts]# echo $[1*2] 2 [root@mico scripts]# echo $[1/2] 0
[root@mico scripts]# typeset -i A=2017 B=2018 [root@mico scripts]# A=A+B [root@mico scripts]# echo $A 4035
# 安裝 bc 依賴於base源 [root@mico scripts]# yum -y install bc 交互模式測試bc命令 [root@mico scripts]# bc bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. 1+1 2 [root@mico scripts]# echo 1+1.1|bc 2.1
[root@mico scripts]# echo 'scale=6;1/3'|bc .333333 python 命令 [root@mico scripts]# file `which yum ` /usr/bin/yum: Python script, ASCII text executable [root@mico scripts]# python >>> import os >>> os.system('df -h') >>> 1+1.1 2.1 >>>exit()
[root@mico ~]# echo "7.7 3.8"|awk '{print ($1-$2)}' 3.9 [root@mico ~]# echo "358 113"|awk '{print ($1-3)/$2}' 3.14159 [root@mico ~]# echo "3 9"|awk '{print ($1+3)*$2}' 54 [root@backup scripts]# awk BEGIN'{print 1.2+3.3}' 4.5
實現腳本:
[root@mico scripts]# cat calculator.sh #!/bin/bash read -p "請輸入第一個整數:" a read -p "請輸入第二個整數:" b echo $a + $b =$(($a+$b)) echo $a - $b =$(($a-$b)) echo $a \* $b =$(($a*$b)) echo $a / $b =$(($a/$b)) 腳本執行過程: [root@mico scripts]# sh calculator.sh 請輸入第一個整數:12 請輸入第二個整數:12 12 + 12 =24 12 - 12 =0 12 * 12 =144 12 / 12 =1
[root@mico scripts]# vim calculator2.sh #!/bin/bash echo $(($1)) 腳本執行過程: [root@mico scripts]# sh calculator2.sh 1+1 2 [root@mico scripts]# sh calculator.sh 1*9 9
腳本內容
[root@mico scripts]# vim count.sh #!/bin/bash Num=`seq -s + 1 10` echo $Num=$(($Num))
腳本執行結果
[root@mico scripts]# sh count.sh 1+2+3+4+5+6+7+8+9+10=55
shell腳本中批量註釋的方法
<<'EOF'
文件內容
EOF
或使用 exit
能夠註釋其以後的全部內容(相似註釋,實質爲不執行後面的內容)