1. 程式人生 > >shell編程基礎-上

shell編程基礎-上

entos this 正常 各類 說明 don 數學運算 cls 重新定義

1.1 前言

1.1.1 為什麽學Shell

Shell腳本語言是實現Linux/UNIX系統管理及自動化運維所必備的重要工具, Linux/UNIX系統的底層及基礎應用軟件的核心大都涉及Shell腳本的內容。每一個合格 的Linux系統管理員或運維工程師,都需要能夠熟練地編寫Shell腳本語言,並能夠閱 讀系統及各類軟件附帶的Shell腳本內容。只有這樣才能提升運維人員的工作效率,適 應曰益復雜的工作環境,減少不必要的重復工作,從而為個人的職場發展奠定較好的基礎

1.1.2 什麽是shell

Shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出屏幕返回給用戶。

這種對話方式可以是:

交互的方式:從鍵盤輸入命令,通過/bin/bash的解析,可以立即得到Shell的回應

[root@clsn ~]# ls            
anaconda-ks.cfg  
[root@clsn ~]# echo ls |bash 
anaconda-ks.cfg   

非交互的方式: 腳本

技術分享圖片

1.1.3 什麽是Shell腳本

命令、變量和流程控制語句等有機的結合起來

shell腳本擅長處理純文本類型的數據,而linux中,幾乎所有的配置文件,日誌,都是純文本類型文件

1.1.4 腳本語言的種類

一、編譯型語言

定義:指用專用的編譯器,針對特定的操作平臺(操作系統)將某種高級語言源代碼一次性翻譯成可被硬件平臺直接運行的二進制機器碼(具有操作數,指令、及相應的格式),這個過程叫做編譯(./configure make makeinstall );編譯好的可執行性文件(.exe),可在相對應的平臺上運行(移植性差,但運行效率高)。。

典型的編譯型語言有, C語言、C++等。

另外,Java語言是一門很特殊的語言,Java程序需要進行編譯步驟,但並不會生成特定平臺的二進制機器碼,它編譯後生成的是一種與平臺無關的字節碼文件(*.class)(移植性好的原因),這種字節碼自然不能被平臺直接執行,運行時需要由解釋器解釋成相應平臺的二進制機器碼文件;大多數人認為Java是一種編譯型語言,但我們說Java即是編譯型語言,也是解釋型語言也並沒有錯。

二、解釋型語言

定義:指用專門解釋器對源程序逐行解釋成特定平臺的機器碼並立即執行的語言;相當於把編譯型語言的編譯鏈接過程混到一起同時完成的。

解釋型語言執行效率較低,且不能脫離解釋器運行,但它的跨平臺型比較容易,只需提供特定解釋器即可。

常見的解釋型語言有, Python(同時是腳本語言)與Ruby等。

三、腳本語言

定義:為了縮短傳統的編寫-編譯-鏈接-運行(edit-compile-link-run)過程而創建的計算機編程語言。

特點:程序代碼即是最終的執行文件,只是這個過程需要解釋器的參與,所以說腳本語言與解釋型語言有很大的聯系。腳本語言通常是被解釋執行的,而且程序是文本文件。

典型的腳本語言有,JavaScript,Python,shell等。

其他常用的腳本語句種類

PHP是網頁程序,也是腳本語言。是一款更專註於web頁面開發(前端展示)的腳本語言,例如:Dedecms,discuz。PHP程序也可以處理系統日誌,配置文件等,php也可以調用系統命令。

Perl腳本語言。比shell腳本強大很多,語法靈活、復雜,實現方式很多,不易讀,團隊協作困難,但仍不失為很好的腳本語言,存世大量的程序軟件。MHA高可用Perl寫的

Python,不但可以做腳本程序開發,也可以實現web程序以及軟件的開發。近兩年越來越多的公司都會要求會Python。

Shell腳本與php/perl/python語言的區別和優勢?

shell腳本的優勢在於處理操作系統底層的業務 (linux系統內部的應用都是shell腳本完成)因為有大量的linux系統命令為它做支撐。2000多個命令都是shell腳本編程的有力支撐,特別是grep、awk、sed等。例如:一鍵軟件安裝、優化、監控報警腳本,常規的業務應用,shell開發更簡單快速,符合運維的簡單、易用、高效原則.

  PHP、Python優勢在於開發運維工具以及web界面的管理工具,web業務的開發等。處理一鍵軟件安裝、優化,報警腳本。常規業務的應用等php/python也是能夠做到的。但是開發效率和復雜比用shell就差很多了。

系統環境說明

[root@clsn scripts]# cat /etc/redhat-release 
CentOS Linux release 7.4.1708 (Core) 
[root@clsn scripts]# uname -r
3.10.0-693.el7.x86_64
[root@clsn scripts]# getenforce 
Disabled
[root@clsn scripts]# 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)

1.1.5 系統中的shell

查看系統中的命解釋器

[root@clsn ~]# cat /etc/shells 
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin

常用操作系統的默認shell

1.Linux是Bourne Again shell(bash)

2.Solaris和FreeBSD缺省的是Bourne shell(sh)

3.AIX下是Korn Shell(ksh)

4.HP-UX缺省的是POSIX shell(sh)

[root@clsn ~]# echo $SHELL
/bin/bash

bash版本

[root@clsn scripts]# 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>

這是自由軟件,您可以自由地更改和重新發布。
在法律允許的範圍內沒有擔保. 

bash 破殼漏洞

使用 命令 env x=‘() { :;}; echo be careful‘ bash -c "echo this is a test"
如果返回結果為一行,則為正常,
 [root@clsn ~]# env x=‘() { :;}; echo be careful‘ bash -c "echo this is a test"
 this is a test
 
#解決辦法 升級當前的bash版本
 yum install update bash

sh與bash 的關系

[root@clsn ~]#  ll /bin/sh
lrwxrwxrwx. 1 root root 4 11月 13 11:15 /bin/sh -> bash

/bin與 /user/bin 的關系

[root@clsn ~]# ll /bin -d
lrwxrwxrwx. 1 root root 7 11月 13 11:15 /bin -> usr/bin

1.2 腳本書寫規範

1.2.1 腳本統一存放目錄

[root@clsn ~]# mkdir -p /server/scripts/
[root@clsn ~]# cd /server/scripts/

1.2.2 選擇解釋器

註意格式 ↓

其中開頭的"#!"字符又稱為幻數,在執行bash腳本的時候,內核會根據"#!"後的解釋器來確定該用那個程序解釋這個腳本中的內容。

[root@clsn scripts]# head -1 /etc/init.d/*
==> /etc/init.d/functions <==
# -*-Shell-script-*-

==> /etc/init.d/netconsole <==
#!/bin/bash

==> /etc/init.d/network <==
#! /bin/bash

1.2.3 編輯腳本使用vim

使用 .vimrc 文件,能夠快速的生成開頭的註釋信息

[root@clsn scripts]# cat  ~/.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: clsn")
        call setline(6, "# Organization: http://blog.znix.top")
        call setline(7, "# Created Time : ".strftime("%F %T"))
        call setline(8, "# Description:")
        call setline(9, "##############################################################")
        call setline(10, "")
    endif
endfunc

使用後的效果

[root@clsn scripts]# cat  scripts_test.sh 
#!/bin/bash
##############################################################
# File Name: scripts_test.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-04 11:39:57
# Description:  First scripts file
##############################################################

在Shell腳本中,跟在#後面的內容表示註釋。註釋部分不會被執行,僅給人看。註釋可以自成一行,也可以跟在命令後面,與命令同行。要養成寫註釋的習慣,方便自己與他人。

最好不用中文註釋,因為在不同字符集的系統會出現亂碼。(字符集為zh_CN.UTF-8,為中文)。

1.2.4 文件名規範

名字要有意義,並且結尾以 .sh 結束

1.2.5 開發的規範和習慣小結

1) 放在統一的目錄

2) 腳本以.sh為擴展名

3) 開頭指定腳本解釋器。

4) 開頭加版本版權等信息,可配置~/.vimrc文件自動添加。

5) 腳本不要用中文註釋,盡量用英文註釋。

6) 代碼書寫優秀習慣

a、成對的內容一次性寫出來,防止遺漏,如[ ]、‘ ‘、" "等

b、[ ]兩端要有空格,先輸入[ ],退格,輸入2個空格,再退格寫。

c、流程控制語句一次書寫完,再添加內容。(if 條件 ; then 內容;fi)ddd

d、通過縮進讓代碼易讀。

f、腳本中的引號都是英文狀態下的引號,其他字符也是英文狀態。

1.3 shell腳本的執行

1.3.1 執行腳本的辦法

sh/bash   scripts.sh 
chown +x   ./scripts.sh  && ./scripts.sh  
source scripts.sh
. (空格) scripts.sh
cat oldboyedu.sh |bash  # 效率較低

source 與 . (點) 的作用

soucre命令

[root@clsn ~]# help source  |head -2
source: source 文件名 [參數]
    在當前 shell 中執行一個文件中的命令。

. (點)

[root@clsn scripts]# help . |head -2
.: . 文件名 [參數]
    在當前 shell 中執行一個文件中的命令。

1.3.2 sh 於 source的區別

技術分享圖片

[root@clsn scripts]# sh  clsn_test.sh 
Hello World!
[root@clsn scripts]# echo $clsn
#  sh  新建一個Shell窗口(新建一個進程)執行一個文件中的命令。

[root@clsn scripts]# source clsn_test.sh 
Hello World!
[root@clsn scripts]# echo $clsn
Hello World!

面試題:

問sh test.sh後echo $user返回的結果__空_ ?

[root@oldboy scripts]# cat test.sh 
#!/bin/bash
user=`whoami`

1.4 Shell的變量

1.4.1 什麽是變量

變量可以分為兩類:環境變量(全局變量)和普通變量(局部變量)

  環境變量也可稱為全局變量,可以在創建他們的Shell及其派生出來的任意子進程shell中使用,環境變量又可分為自定義環境變量和Bash內置的環境變量

  普通變量也可稱為局部變量,只能在創建他們的Shell函數或Shell腳本中使用。普通變量一般是由開發者用戶開發腳本程序時創建的。

特殊變量

1.4.2 環境變量

使用 env/declare/set/export -p 命令查看系統中的環境變量,這三個命令的的輸出方式稍有不同。

[root@clsn scripts]# env
XDG_SESSION_ID=1
HOSTNAME=clsn
TERM=linux
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=10.0.0.1 5537 22
SSH_TTY=/dev/pts/0
USER=root
~~~

輸出一個系統中的 環境變量

[root@clsn ~]# echo $LANG
zh_CN.UTF-8

1.4.3 普通變量

本地變量在用戶當前的Shell生存期的腳本中使用。例如,本地變量OLDBOY取值為bingbing,這個值在用戶當前Shell生存期中有意義。如果在Shell中啟動另一個進程或退出,本地變量值將無效

定義普通變量實踐

[root@clsn ~]# a=1
[root@clsn ~]# b=‘2‘
[root@clsn ~]# c="3"
[root@clsn ~]# echo "$a"
1
[root@clsn ~]# echo "$b"
2
[root@clsn ~]# echo "${c}"

提示:$變量名表示輸出變量,可以用$c和${c}兩種用法

小結:連續普通字符串內容賦值給變量,不管用什麽引號或者不用引號,它的內容是什麽,打印變量就輸出什麽

1.4.4 export命令

[root@clsn ~]# help export 
export: export [-fn] [名稱[=值] ...] 或 export -p
為 shell 變量設定導出屬性。

標記每個 NAME 名稱為自動導出到後續命令執行的環境。如果提供了 VALUE
則導出前將 VALUE 作為賦值。

export命令的說明

當前shell窗口及子shell窗口生效

在新開的shell窗口不會生效,生效需要寫入配置文件

# 定義變量

[root@clsn scripts]# CSLN=clsn
[root@clsn scripts]# export CSLN1=1

# 當前窗口查看

[root@clsn scripts]# echo $CSLN
clsn
[root@clsn scripts]# echo $CSLN1
1

# 編寫測試腳本

[root@clsn scripts]# vim quanju.sh 
#!/bin/bash
echo $CSLN
echo $CSLN1

# 使用sh執行

[root@clsn scripts]# sh  quanju.sh 

1

# 使用source 執行

[root@clsn scripts]# source quanju.sh 
clsn
1

1.4.5 環境變量相關配置文件

/etc/proflie

/etc/bashrc

~/.bashrc

~/.bash_profile

/etc/proflie.d/ # 目錄

四文件讀取順序(CentOS6和7都一樣)

① /etc/profile

② ~/.bash_profile

③ ~/.bashrc

④ /etc/bashrc

技術分享圖片

文件讀取過程示意圖

驗證四文件讀取順序的方法

sed -i ‘1a echo "$(date +%T-%s) /etc/profile1" >>/tmp/clsn‘ /etc/profile
sed -i ‘$a echo "$(date +%T-%s) /etc/profile2" >>/tmp/clsn‘ /etc/profile
sed -i ‘1a echo "$(date +%T-%s) /etc/bashrc1" >>/tmp/clsn‘ /etc/bashrc
sed -i ‘$a echo "$(date +%T-%s) /etc/bashrc2" >>/tmp/clsn‘ /etc/bashrc
sed -i ‘1a echo "$(date +%T-%s) ~/.bashrc1" >>/tmp/clsn‘ ~/.bashrc
sed -i ‘$a echo "$(date +%T-%s) ~/.bashrc2" >>/tmp/clsn‘ ~/.bashrc
sed -i ‘1a echo "$(date +%T-%s) ~/.bash_profile1" >>/tmp/clsn‘ ~/.bash_profile
sed -i ‘$a echo "$(date +%T-%s) ~/.bash_profile2" >>/tmp/clsn‘ ~/.bash_profile

1.4.6 環境變量的知識小結

ü 變量名通常要大寫。

ü 變量可以在自身的Shell及子Shell中使用。

ü 常用export來定義環境變量。

ü 執行env默認可以顯示所有的環境變量名稱及對應的值。

ü 輸出時用“$變量名”,取消時用“unset變量名”。

ü 書寫crond定時任務時要註意,腳本要用到的環境變量最好先在所執行的Shell腳本中重新定義。

ü 如果希望環境變量永久生效,則可以將其放在用戶環境變量文件或全局環境變量文件裏。

1.4.7 變量中引號的使用

只有在變量的值中有空格的時候,會使用引號。

單引號與雙引號的區別在於,是否能夠解析特殊符號。

[root@clsn ~]# name=znix
[root@clsn ~]# name2=‘clsn‘
[root@clsn ~]# name3="http://blog.znix.top"
[root@clsn ~]# echo $name
znix
[root@clsn ~]# echo $name2
clsn
[root@clsn ~]# echo $name3
http://blog.znix.top
[root@clsn ~]# name4=‘cl sn‘
[root@clsn ~]# echo $name4
cl sn
[root@clsn ~]# name5="cl sn"
[root@clsn ~]# echo $name5
cl sn
[root@clsn ~]# name6=‘cl sn $PWD‘
[root@clsn ~]# echo $name6
cl sn $PWD
[root@clsn ~]# name6="cl sn $PWD"
[root@clsn ~]# echo $name6
cl sn /root

1.4.8 普通變量的要求

1) 內容是純數字、簡單的連續字符(內容中不帶任何空格)時,定義時可以不加任何引號,例如:

a.ClsnAge=22

b.NETWORKING=yes

2) 沒有特殊情況時,字符串一律用雙引號定義賦值,特別是多個字符串中間有空格時,例如:

a.NFSD_MODULE="no load"

b.MyName="Oldboy is a handsome boy."

3) 當變量裏的內容需要原樣輸出時,要用單引號(M),這樣的需求極少,例如:

a.OLDBOY_NAME=‘OLDBOY‘

變量使用反引號賦值

[root@clsn scripts]# time=`date`
[root@clsn scripts]# echo $time
2017年 12月 05日 星期二 09:02:06 CST
    
[root@clsn scripts]# file=`ls`
[root@clsn scripts]# echo $file
clsn_test.sh panduan.sh quanju.sh yhk.sh

使用${}

打印變量的時候防止出現“金庸新著”的問題

[root@clsn scripts]# time=`date`
[root@clsn scripts]# echo $time_day

[root@clsn scripts]# echo ${time}_day
2017年 12月 05日 星期二 09:02:06 CST_day
[root@clsn scripts]# echo $time-day
2017年 12月 05日 星期二 09:02:06 CST-day

編寫腳本測試${}

 # 使用腳本測試
 [root@clsn scripts]# vim bianliang.sh 
 #!/bin/bash
 #############################################################
 # File Name: bianliang.sh
 # Version: V1.0
 # Author: clsn
 # Organization: http://blog.znix.top
 # Created Time : 2017-12-05 09:10:29
 # Description:
 #############################################################
    
 time=`date`
 echo $timeday
 echo ${time}day
    
 [root@clsn scripts]# sh  bianliang.sh 
    
 2017年 12月 05日 星期二 09:11:19 CSTday

1.4.9 定義變量名技巧

1. 變量名只能為字母、數字或下劃線,只能以字母或下劃線開頭。

2. 變量名的定義要有一定的規範,並且要見名知意。

示例:

ClsnAge=22 #<==每個單詞的首字母大寫的寫法

clsn_age=22 #<==單詞之間用"_"的寫法

clsnAgeSex=man #<==駝峰語法:首個單詞的首字母小寫,其余單詞首字母大寫

CLSNAGE=22 #<==單詞全大寫的寫法

3. 一般的變量定義、賦值常用雙引號;簡單連續的字符串可以不加引號;希望原樣輸出時使用單引號。

4. 希望變量的內容是命令的解析結果時,要用反引號‘‘,或者用$()把命令括起來再賦值。

1.5 特殊變量

1.5.1 位置變量

常用的特殊位置參數說明

位置變量

作用說明

$0

獲取當前執行的shell腳本的文件名,如果執行腳本帶路徑那麽就包括腳本路徑。

$n

獲取當前執行的shell腳本的第n個參數值,n=1..9,當n為0時表示腳本的文件名,如果n大於9用大括號括起來{10},參數以空格隔開。

$#

獲取當前執行的shell腳本後面接的參數的總個數

$*

獲取當前shell的所有傳參的參數,不加引號同$@;如果給$*加上雙引號,例如: “$*”,則表示將所有的參數視為單個字符串,相當於“112$3”。

$@

獲取當前shell的所有傳參的參數,不加引號同$*;如果給$@加上雙引號,例如: “$@”,則表示將所有參數視為不同的獨立字符串,相當於“$1” “$2” “$3” “……”,這是將參數傳遞給其他程序的最佳方式,因為他會保留所有內嵌在每個參數裏的任何空白。

當“$*”和“$@”都加雙引號時,兩者有區別,都不加雙引號時,兩者無區別。

0,0,1.$2 ~ 參數實踐

[root@clsn scripts]# vim chanshu.sh
#!/bin/bash
############################################################# 
# File Name: chanshu.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 09:39:16
# Description:
############################################################# 
    
echo $0
echo "第一個參數:" $1
echo "第二個參數:" $2
echo "第11個參數:" ${11}
[root@clsn scripts]# sh chanshu.sh
chanshu.sh
第一個參數:
第二個參數:
第11個參數:
[root@clsn scripts]# sh chanshu.sh 1 2 3 4 5 6 7 8 9 10 11 
chanshu.sh
第一個參數: 1
第二個參數: 2
第11個參數: 11

$# 參數實踐

[root@clsn scripts]# vim chanshu.sh
#############################################################
# File Name: chanshu.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 09:39:16
# Description:
#############################################################


echo $0
echo "第一個參數:" $1
echo "第二個參數:" $2
echo "第10個參數:" ${10}
echo "第11個參數:" ${11}
echo "參數個數:" $#



[root@clsn scripts]# sh chanshu.sh 55 2 3 4 5 6 7 8 9 10 11 112
chanshu.sh
第一個參數: 55
第二個參數: 2
第10個參數: 10
第11個參數: 11
參數個數: 12

$* 參數實踐

[root@clsn scripts]# vim chanshu.sh
#############################################################
# File Name: chanshu.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 09:39:16
# Description:
#############################################################

echo $0
echo "第一個參數:" $1
echo "第二個參數:" $2
echo "第10個參數:" ${10}
echo "第11個參數:" ${11}
echo "參數個數:" $#
echo "參數:" $*
"chanshu.sh" 18L, 456C 已寫入                                  
[root@clsn scripts]# sh chanshu.sh 55 2 3 4 5 6 7 8 9 10 11 112
chanshu.sh
第一個參數: 55
第二個參數: 2
第10個參數: 10
第11個參數: 11
參數個數: 12
參數: 55 2 3 4 5 6 7 8 9 10 11 112

$* 與 $@ 對比實踐

[root@clsn scripts]# set -- "I am" handsome boy..
[root@clsn scripts]# echo $1
I am
[root@clsn scripts]# echo $2
handsome
[root@clsn scripts]# echo $3
boy..
[root@clsn scripts]# echo $*
I am handsome boy..
[root@clsn scripts]# echo $@
I am handsome boy..

[root@clsn scripts]# for i in $*;do echo $i ;done
I
am
handsome
boy..
[root@clsn scripts]# for i in $@;do echo $i ;done
I
am
handsome
boy..
[root@clsn scripts]# for i in "$@";do echo $i ;done
I am
handsome
boy..
[root@clsn scripts]# for i in "$*";do echo $i ;done
I am handsome boy..

1.5.2 進程狀態變量

Shell進程的特殊狀態變量說明

位置變量

作用說明

$?

獲取執行上一個指令的執行狀態返回值(0為成功,非零為失敗),這個變量最常用

$$

獲取當前執行的Shell腳本的進程號(PID),這個變量不常用,了解即可

$!

獲取上一個在後臺工作的進程的進程號(PID),這個變量不常用,了解即可

$_

獲取在此之前執行的命令或腳本的最後一個參數,這個變量不常用,了解即可

進程參數實踐

[root@clsn scripts]# echo $?
0
[root@clsn scripts]# echo $$
1368
[root@clsn scripts]# echo $!

[root@clsn scripts]# echo $_
echo

1.5.3 echo參數說明

參數

參數說明

-n

不要追加換行

-e

啟用下列反斜杠轉義的解釋

-E

顯式地抑制對於反斜杠轉義的解釋

`echo‘ 對下列反斜杠字符進行轉義:

\n

換行

\r

回車

\t

橫向制表符

\b

退格

\v

縱向制表符

\c

抑制更多的輸出

1.6 定義變量的方式

1.6.1 三種定義變量的方式

1、直接賦值

2、傳參 (傳遞參數)

3、交互式設置變量,使用read命令

1.6.2 read命令說明

在命令行中使用

[root@clsn scripts]# read
132
[root@clsn scripts]# echo $REPLY 
132
[root@clsn scripts]# read clsn 
456
[root@clsn scripts]# echo $clsn
456
[root@clsn scripts]# echo $REPLY 
132

在腳本中使用

[root@clsn scripts]# vim clsn_test.sh 
#!/bin/bash
read -p ‘請輸入:‘  clsn

echo $clsn

執行結果

[root@clsn scripts]# sh clsn_test.sh 
請輸入:clsn_znix
clsn_znix

read命令的幫助說明

[root@clsn scripts]# read --help
-bash: read: --: 無效選項
read: 用法:read [-ers] [-a 數組] [-d 分隔符] [-i 緩沖區文字] [-n 讀取字符數] [-N 讀取字符數] [-p 提示符] [-t 超時] [-u 文件描述符] [-s不顯示終端的任何輸入] [名稱 ...]

1.6.3 定義方法實踐

直接賦值方法

[root@clsn scripts]# vim bianliang.sh
# File Name: bianliang.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 09:10:29
# Description:
##############################################################
name=CLSN
age=22
sex=Man
hobby=`ls`
ethFile=/etc/sysconfig/network-scripts/ifcfg-eth0

echo $hobby
ls $ethFile
[root@clsn scripts]# sh  bianliang.sh
bianliang.sh chanshu.sh clsn.sh clsn_test.sh panduan.sh quanju.sh xiugaizhuji.sh yhk.sh
/etc/sysconfig/network-scripts/ifcfg-eth0

傳參 (傳遞參數)

[root@clsn scripts]# vim bianliang.sh
##############################################################
# File Name: bianliang.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 09:10:29
# Description:
##############################################################
name=CLSN
age=22
sex=Man
hobby=$1
ethFile=$2

echo $hobby
ls $ethFile
[root@clsn scripts]# sh  bianliang.sh  clsn /etc/hostname 
clsn
/etc/hostname

交互式設置變量 read

[root@clsn scripts]# vim yhk.sh 
#!/bin/bash
##############################################################
# File Name: yhk.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-04 17:01:44
# Description:
##############################################################
read -p  "請輸入你的銀行卡號:"  Yhk
read -s -p  "請輸入密碼:" miMa
echo
echo "你的銀行卡號:"  $Yhk
echo "你的密碼為:" $miMa
# 測試結果
[root@clsn scripts]# sh  yhk.sh 
請輸入你的銀行卡號:123456
請輸入密碼:
你的銀行卡號: 123456
你的密碼為: 123456

1.6.4 寫一個交互腳本,實現能夠定義主機名及IP地址

腳本內容

[root@clsn scripts]# cat xiugaizhuji.sh 
#!/bin/bash
#############################################################
# File Name: jiaohu.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 10:55:42
# Description:
#############################################################

ethFile=/etc/sysconfig/network-scripts/ifcfg-eth[01]
Now_eth=`hostname -I|awk -F "[. ]+" ‘{print $4}‘`

read -p "請輸入主機名:" Hostname
read -p "請輸入IP地址的主機位:" HostIP

hostnamectl set-hostname  $Hostname
 
sed  -i "s#${Now_eth}#${HostIP}#g" $ethFile 

read -p "是否重啟服務器:{yes/no}"  REboot

if [ $REboot == yes ]
then 
   echo "系統將在10秒後重啟!"
   shutdown -r  10 
else
   echo "請稍後手動重啟系統!"
fi

腳本測試結果

[root@clsn scripts]# sh xiugaizhuji.sh
請輸入主機名:clsn
請輸入IP地址的主機位:180
是否重啟服務器:{yes/no}yes
系統將在10秒後重啟!
[root@clsn scripts]# sh xiugaizhuji.sh
請輸入主機名:clsn
請輸入IP地址的主機位:180
是否重啟服務器:{yes/no}no
請稍後手動重啟!

1.7 變量的子串

1.7.1 變量子串說明

表達式

說明

${parameter}

返回變量$parameter的內容

${#parameter}

返回變內容的長度(按字符),也適用於特殊變量

${parameterioffset}

在變量${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@clsn scripts]# clsn=http://blog.znix.top
[root@clsn scripts]# echo ${clsn} |wc -L 
20
[root@clsn scripts]# echo ${#clsn} 
20
[root@clsn scripts]# time echo ${clsn} |wc -L 
20

real    0m0.002s
user    0m0.002s
sys    0m0.000s
[root@clsn scripts]# time echo ${#clsn} 
20

real    0m0.000s
user    0m0.000s
sys    0m0.000s

截取變量中的字符

[root@clsn scripts]# clsn=abcABC123ABCabc
[root@clsn scripts]# echo ${clsn#abc}
ABC123ABCabc
[root@clsn scripts]# echo ${clsn##abc}
ABC123ABCabc
[root@clsn scripts]# echo ${clsn%abc}
abcABC123ABC
[root@clsn scripts]# echo ${clsn%%abc}
abcABC123ABC
[root@clsn scripts]# echo ${clsn#a*c}
ABC123ABCabc
[root@clsn scripts]# echo ${clsn##a*c}

[root@clsn scripts]# echo ${clsn%a*c}
abcABC123ABC
[root@clsn scripts]# echo ${clsn%%a*c}

[root@clsn scripts]# echo ${clsn#a*C}
123ABCabc
[root@clsn scripts]# echo ${clsn#a*C}
123ABCabc
[root@clsn scripts]# echo ${clsn##a*C}
abc
[root@clsn scripts]# echo ${clsn%a*c}
abcABC123ABC
[root@clsn scripts]# echo ${clsn%A*c}
abcABC123
[root@clsn scripts]# echo ${clsn%%A*c}
abc

替換變量內容

[root@clsn scripts]# echo $clsn
abcABC123ABCabc
[root@clsn scripts]# echo ${clsn/abc/clsn}
clsnABC123ABCabc
[root@clsn scripts]# echo ${clsn//abc/clsn}
clsnABC123ABCclsn

有關上述匹配刪除的小結

#表示從幵頭刪除匹配最短。

##表示從開頭刪除匹配最長。

%表示從結尾刪除匹配最短。

%%表示從結尾刪除匹配最長。

a*c表示匹配的突符串,*表示匹配所有,a*c匹配開頭為a、中間為任意多個字符、結尾為c的字符串。

a*C表示匹配的字符串,*表示匹配所有,a*C匹配開頭為a、中間為任意多個字符、結尾為C的字符串。

有關替換的小結

一個“/”表示替換匹配的第-個字符串。

兩個“/”表示替換匹配的所有字符串。

1.7.2 Shell的特殊擴展變量說明

表達式

${parameter:-word}

如果parameter的變量值為空或未賦值,則會返回word字符串並替代變量的值用途.如果變量未定義,則返回備用的值,防止變量為空值或因未定義而導致異常

${parameter:=word}

如果parameter的變量值為空或未賦值,則設置這個變量值為word,並返回其值。位置變量和特殊變量不適用用途:基本同上一個${parameter>word},但該變量又額外給parameter變量賦值了

${parameter:?word}

如果parameter變量值為空或未賦值,那麽word字符串將被作為標準錯誤輸出,否則輸出變量的值。用途:用於捕捉由於變量未定義而導致的錯誤,並退出程序

${parameter:+word}

如果parameter變量值為空或未賦值,則什麽都不做,否則word字符串將替代變量的值

特殊變量實踐

腳本內容

[root@clsn scripts]# cat  clsn.sh 
#!/bin/bash
#############################################################
# File Name: clsn.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-05 12:13:38
# Description:
#############################################################
dir=
echo ${dir:-/tmp}
echo ${dir}
echo ${dir:=/mnt}
echo ${dir}
dir2= (空格)
echo ${dir2-/tmp}
echo ${dir2}
echo ${dir2:-/tmp}
echo ${dir2}
echo ${dir2=/mnt}
echo ${dir2}

測試結果

[root@clsn scripts]# sh clsn.sh 
/tmp

/mnt
/mnt


/tmp

至此shell中的變量就都介紹完了

1.8 變量的數值計算

1.8.1 僅支持整數的運算

echo $((數學運算表達式))

# 形式一
[root@clsn scripts]# echo $((1 + 1))
2
[root@clsn scripts]# echo $((2*7-3/6+5))
19
# 形式二
[root@clsn scripts]# ((clsn=2*8))
[root@clsn scripts]# echo $clsn
16
# 形式三
[root@clsn scripts]# znix=$((2*7-3/6+5))
[root@clsn scripts]# echo $znix
19

延伸產物(重要)

i++ 自增1

i-- 自減1

++i

--i

示例:

[root@clsn scripts]# i=1
[root@clsn scripts]# echo $((i++))
1
[root@clsn scripts]# echo $((i++))
2
[root@clsn scripts]# echo $((i--))
3
[root@clsn scripts]# echo $((i--))
2
[root@clsn scripts]# echo $((i--))
1
[root@clsn scripts]# echo $((++i))
1
[root@clsn scripts]# echo $((++i))
2
[root@clsn scripts]# echo $((++i))
3
[root@clsn scripts]# echo $((--i))
2
[root@clsn scripts]# echo $((--i))
1
[root@clsn scripts]# echo $((--i))
0

記憶方法:++,--

變量a在前,表達式的值為a,然後a自增或自減,變量a在符號後,表達式值自增或自減,然後a值自增或自減。

let命令

[root@clsn scripts]# i=1
[root@clsn scripts]# i=i+1
[root@clsn scripts]# echo $i
i+1

[root@clsn scripts]# i=1
[root@clsn scripts]# let i=i+1
[root@clsn scripts]# echo $i
2

expr 命令

1.整數計算

2.判斷擴展名

3.判斷輸入是否為整數,非整數返回值為2

4.計算變量的長度

[root@clsn scripts]# expr 1+1
1+1
[root@clsn scripts]# expr 1 + 1
2
[root@clsn scripts]# expr 1 * 1
expr: 語法錯誤
[root@clsn scripts]# expr 1 \* 1
1

非整數返回值為2 示例:

[root@clsn scripts]# expr 1 + 1 
2
[root@clsn scripts]# echo $?
0
[root@clsn scripts]# expr -1 + 1 
0
[root@clsn scripts]# echo $?
1
[root@clsn scripts]# expr a + 1 
expr: 非整數參數
[root@clsn scripts]# echo $?
2

$[]運算符

[root@clsn scripts]# echo $[1+2]
3
[root@clsn scripts]# echo $[1-2]
-1
[root@clsn scripts]# echo $[1*2]
2
[root@clsn scripts]# echo $[1/2]
0

typeset命令進行運算

[root@clsn scripts]# typeset -i A=2017 B=2018
[root@clsn scripts]# A=A+B
[root@clsn scripts]# echo $A
4035

1.8.2 可以進行小數運算的命令

bc 命令

# 安裝 bc  依賴於base源
[root@clsn scripts]# yum -y install bc

交互模式測試bc命令

[root@clsn scripts]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. 
1+1
2
[root@clsn scripts]# echo 1+1.1|bc
2.1

免交互模式測試bc命令

[root@clsn scripts]# echo ‘scale=6;1/3‘|bc
.333333

python 命令

[root@clsn scripts]#  file `which yum `
/usr/bin/yum: Python script, ASCII text executable
[root@clsn scripts]# python 
>>> import os
>>> os.system(‘df -h‘)
>>> 1+1.1
2.1
>>>exit()

awk 命令

[root@clsn ~]# echo "7.7 3.8"|awk ‘{print ($1-$2)}‘
3.9
[root@clsn ~]# echo "358 113"|awk ‘{print ($1-3)/$2}‘
3.14159
[root@clsn ~]# echo "3 9"|awk ‘{print ($1+3)*$2}‘
54
[root@backup scripts]# awk BEGIN‘{print 1.2+3.3}‘
4.5

1.8.3 運算相關練習題

1.8.3.1 【練習題】實現一個加減乘除等功能的計算器

實現腳本:

[root@clsn scripts]# cat jishuanqi.sh 
#!/bin/bash
#############################################################
# File Name: jishuanqi.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-06 08:57:13
# Description:
#############################################################

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@clsn scripts]# sh jishuanqi.sh 
請輸入第一個整數:12
請輸入第二個整數:12
12 + 12 =24
12 - 12 =0
12 * 12 =144
12 / 12 =1

精簡方法

[root@clsn scripts]# vim jishuanqi2.sh 
#!/bin/bash
#############################################################
# File Name: jishuanqi2.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-06 15:02:41
# Description:
#############################################################
echo $(($1))

腳本執行過程:

[root@clsn scripts]# sh jishuanqi2.sh  1+1
2
[root@clsn scripts]# sh jishuanqi2.sh  1*9
9

1.8.3.2 【練習題】打印結果1+2+3+4+5+6+7+8+9+10=55

腳本內容

[root@clsn scripts]# vim yunshuan.sh
#!/bin/bash
#############################################################
# File Name: yunshuan.sh
# Version: V1.0
# Author: clsn
# Organization: http://blog.znix.top
# Created Time : 2017-12-06 09:40:31
# Description:
#############################################################

Num=`seq -s + 1 10`
echo  $Num=$(($Num))

腳本執行結果

[root@clsn scripts]# sh  yunshuan.sh
1+2+3+4+5+6+7+8+9+10=55

1.9 補充說明

shell腳本中批量註釋的方法

<<‘EOF‘
文件內容
EOF
   或
   使用 exit可以註釋其之後的所有內容(類似註釋,實質為不執行後面的內容)

1.9.1 參考文獻

http://blog.csdn.net/lansesl2008/article/details/20558369

https://www.abcdocker.com/abcdocker/269

http://blog.51cto.com/life2death/1657133

shell編程基礎-上