【Linux】shell基礎之符號篇

我們以前可能也聽過shell這個名詞,但是並未深入瞭解,本片博客旨在揭開shell神祕的面紗。
一、與shell相關的一些概念的介紹
1、Shell定位、
(1)Shell是一種用c語言編寫的程序,它是用戶使用Linux的橋樑。Shell既是一種命令語言又是一種程序設計語言
(2)Shell是指一種應用程序,一種和內核溝通的外殼應用程序的統稱。有時會提供一個界面,用戶通過這個界面訪問操作系統內核的服務
2、Shell和Bash
Bash就是一種常見的Shell,形象的來說,Shell叫做媒婆,Bash就是王婆,是一種包含關係
3、Shell腳本
(1)Shell腳本,是一種爲shell編寫的腳本程序
(2)通常所說的shell通常都是指shell腳本,但是,shell和shell script是兩種不同的概念
(3)由於習慣的原因,我們認爲“shell編程”都是指shell腳本編程
4、Shell開發環境
(1)Shell編程和java、php、python編程一樣,只要有一個文本編輯器和一個解釋器就可以了
(2)Linux的Shell解釋器種類很多常見的有:Bource Shell(/usr/bin/sh或者/bin/sh)、Bource Again Shell(/usr/bin/bash)、C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)、Shell for Root(/sbin/sh)
(3)我們關注的是Bash,也就是Bourne Again Shell,也就是大多數Linux系統默認的Shell
5、shell特點
(1)解釋非編譯型
(2)弱類型
(3)執行模式:交互式/批處理式
一個簡單的Shell腳本
這裏寫圖片描述
注意:(1)#!是一個約定的標記,用於告訴系統使用那一種解釋器,即使用哪一種shell,通常(#!)叫做“Shebang”或者“Sha-bang”
(2)echo命令用於向窗口輸出文本
執行shell腳本有兩種方式:
(1)給shell腳本加一個可執行權限就可以直接用./加上腳本文件來執行
如果不加./直接寫文件名字,linux系統會在PATH裏尋找,我們寫的程序一般都不在PATH裏,所以就無法執行,而./就相當於告訴系統這個文件就在當前目錄下
(2)前面加上解釋器,把該shell文件作爲解釋器的參數來執行
這種執行方式,直接運行解釋器,參數就是文件名,不需要在第一行指定解釋器信息,寫了也用不到
這裏寫圖片描述
shell腳本中用#表示註釋
但是如果#位於第一行開頭例外,表示該腳本使用後面的解釋器來解釋
6、解釋執行本質原理
(1)第一種執行方式,加可執行權限,shell會fork一個子進程並調用exec執行./first.sh這個程序,exec系統調用應該把子進程的代碼段替換成./first.sh程序的代碼段,並從它的_start開始執行
(2)然而first.sh是個文本文件,根本沒有代碼段和_start函數,其實exec還有另外一種機制,如果要執行的是一個文本文件,並且第一行用Shebang指定了解釋器,則用解釋器程序的代碼段替換當前進程,並且從解釋器的_start開始執行,而這個文本文件被當做命令行參數傳給解釋器
(3)交互Shell(bash)fork/exec一個子Shell用於執行腳本,父進程bash等待子進程終止
(4)sh讀取腳本中的cd ..命令,調用相應的函數執行內建命令改變當前工作目錄爲上一級目錄
(5)sh讀取腳本中的ls命令,fork/exec這個程序,列出當前目錄下的文件sh等待ls終止
(6)ls終止後,sh繼續執行,讀到腳本文件末尾,sh終止
(7)sh終止後,bash繼續執行,打印提示符等待用戶輸入
這裏寫圖片描述
由圖中發現雖然打印出來的目錄變了,可是直接在命令行輸入pwd發現目錄並沒有改變,這個解釋就是這裏用創建子進程來解釋腳本
這裏寫圖片描述
可是直接在命令行上執行上面的命令發現目錄改變了,兩個過程都是用同樣的命令,爲什麼結果不同呢?說好的創建子進程呢?實際上,執行命令並不是一定要創建子進程,這些不需要創建子進程的命令叫做shell的內置命令,由父bash親自執行,可以將該類命令理解成shell的內部函數即可。
這裏寫圖片描述
這裏寫圖片描述
我們發現,用. 或者source修飾腳本,腳本的執行影響到了父bash,這種方式不會創建子Shell
二、Shell變量
shelll是弱類型語言,原則上不需要強調shell變量,或者shell可以放很多常見內容,shell變量也不需要提前定義,或者不牽扯到定義一說,需要時直接使用即可
1、賦值命名規則
注意變量和等號之間不能有空格否則會被解釋成命令,變量名的命名必須遵循如下規則:
(1)首個字符必須爲字母(a-z,A-Z)
(2)中間不能有空格,可以使用下劃線
(3)不能使用標點符號
(4)不能使用bash裏面的關鍵字(可以help查看)
2、shell變量可以放入你想放入的很多內容
這裏寫圖片描述
3、使用變量
想要使用一個賦值過的變量,只要在變量前面加$符號即可
這裏寫圖片描述
可以看出我們想輸出得是hello worldhello bit,實際上只輸出了部分,原因是shell將mystring和hello認爲成了一個新的變量名,而這個變量名沒有被賦值所以位空串
這裏寫圖片描述
當我們加上一個大括號之後結果就能正確輸出了,加大括號的作用是幫助解釋器識別變量的邊界,所以應該養成給每一個變量加上大括號的習慣

已定義的變量,可以被重新定義
但是第二次賦值時,變量名前面不能加“$”,加上$只能做右值
4、只讀變量
使用readonly命令可以將變量定義爲只讀變量,只讀變量的值不能被改變
這裏寫圖片描述
5、刪除變量
使用unset命令可以刪除變量
這裏寫圖片描述
unset不能刪除只讀變量
這裏寫圖片描述
6、變量類型
我們前面提到了shell腳本是弱類型,也有變量類型嗎,shell的變量類型和c/c++變量類型有點不一樣
(1)本地變量:局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啓動的程序不能訪問局部變量
(2)環境變量:所有的程序,包括shell啓動的程序都能訪問環境變量,有些程序需要環境變量來保證其正常運行,必要的時候shell腳本也可以定義環境變量
(3)shell變量:shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行
這裏寫圖片描述
我們在父shell上定義了一個變量,直接交互式父shell中,訪問是可以直接訪問的,但是在子腳本中訪問,卻訪問不到
這裏寫圖片描述
將myval變量導成環境變量子shell就可以訪問到了
7、拼接字符串
原則上只要將信息寫在一起,就完成了string的拼接,當然有一些特殊的地方
這裏寫圖片描述
(1)獲取字符串長度
這裏寫圖片描述
(2)提取字符串
這裏寫圖片描述
(3)查找字符串
這裏寫圖片描述
三、文件名代換::*?[]
這些用於匹配的字符稱爲通配符
(1)通配符*:匹配0個或多個任意字符
(2)?:匹配任意一個字符的一次出現
(3)[若干字符]:匹配方括號中任意一個字符的一次出現
這裏寫圖片描述
注意:Globbing所匹配的文件名是由Shell展開的,也就是說在參數還沒傳給程序之前已經展開了,比如上面ls file[1-5]命令,如果當前目錄下有file1-file5,則傳給ls命令的參數實際上是這5個文件名,而不是一個匹配字符串
四、命令代換和算術代換
由反引號“括起來的也是一條命令,Shell先執行該命令然後將輸出結果立刻代換到當前命令行中
這裏寫圖片描述
命令代換也可以用$()表示:DATE=$(date +%Y:%m:%d)
(())中的shell變量取值將轉換成整數,常用於算術計算,例如:
這裏寫圖片描述
如果要對運算結果進行賦值或者作爲右值
這裏寫圖片描述
(())中只能用+-*/和()運算符,並且只能做整數運算
五、轉義字符
和c語言類似,\在Shell中被用作轉義字符,用於去除緊跟在後面的單個字符的特殊意義(回車除外),換句話說,緊跟在其後的字符字面值。另外,\還可以緊跟其後面字符取特殊含義
這裏寫圖片描述
另外還有一個字符雖然不具有特殊含義,但是要用它做文件名也很麻煩,就是.號。如果創建一個文件名以.號開頭的文件,這樣是不行的:即使加上\轉義還是報錯,因爲各種unix命令都把.號開頭的命令行參數作爲命令的選項而不會當做文件名,,如果非要處理以.開頭的文件名可以有兩種辦法
這裏寫圖片描述
\還有一種用法,在\後敲回車換行表示續行,Shell並不會立刻執行命令,而是把光標移到下一行,給出一個續航提示符>等待用戶繼續輸入,最後把所有的續行接在一起當做一個命令執行
這裏寫圖片描述
六、單引號雙引號
和c語言不一樣,Shell腳本中的單引號和雙引號一樣都是字符串的界定符。單引號用於保持引號內所有字符的字面值,即使引號內的\和回車也不例外,但是字符串中不能出現單引號。如果引號沒有配對就輸入回車,Shell會給出續行提示符,要求用戶把引號配上對
這裏寫圖片描述
(1)$加變量名可以去變量的值
(2)反引號仍表示命令替換
(3)$表示$的字面值
(4)反引號表示的字面值
(5)\”表示”的字面值
(6)\表示\的字面值除以上情況之外,在其它字符前面的\無特殊含義,只表示字面值

發佈了108 篇原創文章 · 獲贊 134 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章