初識shell程式設計

日子總要往前走發表於2021-01-03

1.什麼是shell程式設計

為了搞清楚這個問題,我們先搞清楚程式語言的大體分類。

程式語言
機器語言
組合語言
高階語言
靜態語言
動態語言
c語言
c++
java
c#
php
shell
python
perl
lua

1.1 程式語言大體上包括哪些?以及涉及到的分類?

程式語言總體分為機器語言、組合語言、高階語言

  • 機器語言:由於計算機內部只能接受二進位制程式碼,因此,用二進位制程式碼0和1描述的指令稱為機器指令,全部機器指令的集合構成計算機的機器語言。
  • 組合語言:組合語言的實質和機器語言是相同的,都是直接對硬體操作,只不過指令採用了英文縮寫的識別符號,更容易識別和記憶。它同樣需要程式設計者將每一步的操作用命令的形式寫出來。彙編程式的每一句指令只能對應實際操作過程中的一個很細微的動作。例如移動、自增,因此彙編程式一般比較冗長、複雜、容易出錯,而且使用匯編語言程式設計需要有更多的計算機專業知識,但組合語言的優點也是顯而易見的,用匯編語言所能完成的操作不是一般高階語言所能夠實現的,而且源程式經彙編生成的可執行檔案不僅比較小,而且執行速度很快。
  • 高階語言
    • 高階語言是大多數程式設計者的選擇。和組合語言相比,它不但將許多相關的機器指令合成單條指令,並且去掉了與具體操作有關但與完成工作無關的細節,例如使用堆疊、暫存器等,這樣就大大簡化了程式中的指令。同時,由於省略了很多細節,程式設計者也就不需要有太多的專業知識。
    • 高階語言主要是相對於組合語言而言,它並不是特指某一種具體的語言,而是包括了很多程式語言,像最簡單的程式語言PASCAL語言也屬於高階語言。

1.2 高階語言又可以分為動態語言和靜態語言,是怎麼分的?

  • 首先高階語言所編制的程式不能直接被計算機識別,必須經過轉換才能被執行,按照轉換的方式可以將它們分為兩類:動態語言和靜態語言
    • 靜態語言又叫做編譯類語言,通常是一種變數強型別語言。編譯是指應用源程式執行之前,就將程式原始碼“翻譯成”目的碼(機器語言),因此其目標程式可以脫離其語言環境獨立執行(編譯後生成的可執行檔案,是cpu可以理解的2進位制的機器碼組成的),使用比較方便、效率較高。但應用程式一旦需要修改,必須先修改原始碼,再重新編譯生成新的目標檔案(*.obj,也就是OBJ檔案)才能執行,只有目標檔案而沒有原始碼,修改很不方便。比如:c語言、c++,java,c#等。
    • 動態語言又叫做解釋類語言,通常是一種變數弱型別語言,依賴於直譯器。執行方式類似於我們日常生活中的“同聲翻譯”,應用源程式一邊由相應的語言直譯器“翻譯”成目的碼(機器語言),一邊執行,因此效率比較低,而且不能生成可獨立執行的可執行檔案,應用程式不能脫離其直譯器(想執行,必須先裝上直譯器,就像跟老外說話,必須有翻譯在場),但這種方式比較靈活,可以動態地調整、修改應用程式。如asp、aps.net、php、shell、python、perl、lua,ruby等。

1.3 什麼是物件導向,什麼是程式導向,二者有什麼區別?

  • 物件導向:
    物件導向(Object Oriented,OO)的思想對軟體開發相當重要,它的概念和應用甚至已經超越了程式設計和軟體開發,擴充套件到如資料庫系統、互動式介面、應用架構、分散式系統、網路管理、CAD技術、人工智慧等領域。物件導向是一種對現實世界理解和抽象的方法,是計算機程式設計技術發展到一定階段後的產物。
  • 程式導向:
    程式導向(Procedure Oriented)是一種以過程為中心的程式設計思想。這些都是以正在發生為主要目標進行程式設計,不同於物件導向的是誰在受影響。與物件導向明顯不同的就是封裝、繼承、類。
  • 主要是物件導向的語言有JAVA,Python,C++,程式導向的語言有Shell,C,其中perl既有物件導向的特性又有程式導向的特性。

1.4 shell程式設計是什麼?

扯了半天,我們搞清楚了程式語言的分類以及靜態和動態語言的區別。那麼接下來就好說了:
首先shell是一種程式導向的動態語言,它依賴於各種各樣的bash指令碼直譯器(直譯器通常是靜態語言開發的),shell程式設計實際上也就是一種指令碼程式設計。

2.變數

2.1 變數的概念

 從本質上來看,變數代表了一段可操作的記憶體,也可以認為變數是記憶體的符號化表示(命名的記憶體空間),記憶體是編止的儲存單元。
 一個程式執行起來之後就成了程式,程式所涉及到的所有資料和指令都是存在記憶體中的。當程式執行過程中需要臨時儲存一些資料的時候就需要用到變數。

2.1.1 變數型別的概念

 變數型別決定了變數儲存的大小和格式,該範圍內的值都可以儲存在記憶體中,運算子可應用於變數上。

2.1.2 常見的變數型別

  • 字元
  • 數值
    • 整型
    • 浮點型:11.23,1.123* 10^1 , 0.1123* 10^2
  • 日期 2013/10/10
  • 布林型
    • 真、假(邏輯:1+1>2)

2.2 什麼是強型別語言,什麼是弱型別語言?

這裡是學術界的一種較為嚴格的說法,為了解釋強型別,弱型別,我們需要先弄清楚以下概念:

  • Program Errors
    • trapped errors:導致程式終止執行,如除0,Java中陣列越界訪問
    • untrapped errors:出錯後繼續執行,但可能出現任意行為。如C裡的緩衝區溢位、Jump到錯誤地址。
  • Forbidden Behaviours
     語言設計時,可以定義一組forbidden behaviors。它必須包含所有的untrapped errors,但可能包含trapped errors。
  • Well behaved、ill behaved
    • well behaved:如果程式執行不可能出現forbidden behaviours,則為well behaved
    • ill behaved:如果程式執行可能出現forbidden behaviours,則為ill behave
      下來就可以討論強型別和弱型別了:
  • 強型別(strongly typed):如果一種語言的所有程式都是well behaved——即不可能出現forbidden behaviors,則該語言為strongly typed。
  • 弱型別(weakly typed):如果一種語言可能出現ill behaved——即可能出現forbidden behaviors,則該語言為weakly typed。
     強型別語言的變數在使用前,必須事先宣告型別,甚至需要進行初始化。
     強型別語言通常情況下:每個變數和物件都必須宣告型別,他們是在編譯的時候就確定型別的資料,在執行時型別不能修改。
     弱型別語言的變數隨用隨宣告,甚至不區分型別,一般預設都為字串(11+b=11b)

2.3 強弱型別與動靜態的大致關係

  • 通常來說,編譯型語言也就是靜態語言沒有額外處理邏輯,是強型別語言
  • 指令碼型語言(動態語言)通常有直譯器來控制,可以是弱型別語言,shell就是一種弱型別語言
  • 對於大多數靜態語言來說宣告變數時必須確定變數型別。
  • 弱型別語言在執行的時候才會確定型別。

2.4 顯式轉換與隱式轉換

  • 顯示轉換是強制轉換,由高階型別轉為低階型別,須使用者在程式碼中明確指定
  • 隱式轉換是編譯器自動轉換的,一般同一資料型別,由低階轉為高階為隱式(如int轉為float或double)
    如:11+c 通常11和c都會被轉換成對應的ASRII碼值,然後進行相加
  • 編譯型語言是在編譯時進行轉換的,解釋型語言是在直譯器執行的時候進行解釋的

2.5 變數賦值

  • 變數賦值的一般形式為:VAR_NAME=VALUE
  • 不同語言賦值方式不盡相同

3.邏輯運算

3.1 基本邏輯運算子

  • 與運算(&)
     進行運算的兩個資料,按二進位制位進行“與”運算。
     規則:
    • 0&0=0
    • 0&1=0
    • 1&0=0
    • 1&1=1
  • 或運算(|)
     進行計算的兩個資料,按二進位制位進行“或”運算。
     規則:
    • 0|0=0
    • 0|1=1
    • 1|0=1
    • 1|1=1
  • 非運算(!)
     1取0,0取1。
     規則:
    • ~1=0
    • ~0=1
  • 異或運算(^)
     進行計算的兩個資料,按二進位制位進行“異或”運算。
     規則:運算元相同為假,不同則為真
    • 0^0=0
    • 0^1=1
    • 1^0=1
    • 1^1=0
       運算元相同得0,不同得1。

3.2 短路運算

3.2.1 什麼&&和||的短路運算?

  • 表示式1&&表示式2:只要任意表示式為false,則整個表示式的運算結果為false
  • 表示式1||表示式2:只要任意表示式為true,則整個表示式的運算結果為true

3.2.2 &&和||的短路運算有什麼用?

 如果在前面的表示式的運算過程,通過判斷已經明確的知道整個表示式的結果,那麼就不會進行後面表示式的運算判斷。

4.shell中的變數

4.1 shell的變數分類

需要注意的是:這裡是按照變數本身的作用範圍,以及變數本身的表示形式來講,來區分變數型別

變數分類
環境變數
本地變數
位置變數
特殊變數

4.1.1 區域性變數

  • 定義在指令碼函式中的變數叫做區域性變數
  • 定義方式:local VARNAME=VALUE
  • 區域性變數的作用域只對當前程式碼段有效

4.1.2 本地變數

  • 定義在bash或shell指令碼中的變數,需要注意:
    • 定義在bash中時候,定義後,bash的任何位置都可訪問該變數
    • 定義在shell指令碼中,定義後,shell指令碼程式碼在定義後的程式碼位置都可訪問該變數
  • 定義方式:VARNAME=VALUE
  • 作用域:整個指令碼程式或者整個bash程式
    • 注意:變數一定是用在某個程式中的,是程式執行過程中用來儲存資料的。而bash就是一種特殊的程式,bash執行起來後就需要使用bash中宣告的變數,這個變數和bash程式有關,一旦bash程式結束,那麼在bash中宣告的變數也就消失了,變數是程式的變數
    • 例如:從父shell進入子shell,父shell定義的變數在子shell中並不存在因為父子shell是兩個程式
      需要注意一點:區域性變數不一定是本地變數

4.1.3 環境變數

  • 定義方式為export VARNAEM=VALUE的變數就是環境變數
  • 定義方式:
    • export VARNAME=VALUE
    • 也可分為兩步:先定義成本地變數,然後再匯出(export)
  • 作用域:當前shell程式及其子程式
    • 這裡需要知道:在命令提示符下執行的任何一個指令碼,在自己執行時會啟動一個子shell程式
    • 所以需要注意:
      • 命令列中啟動的指令碼會繼承當前shell環境變數
      • 系統自行執行的指令碼(非命令列啟動)就需要自我定義需要的各環境變數

4.1.4 位置變數

$1,$2,… 第一個位置變數,第二個位置變數… 用來引用指令碼的引數

4.1.5 特殊變數

這些變數是bash內建的,用來儲存某些特殊資料的變數,也可以叫做系統變數
例如:

  • $?:上一個命令的執行狀態返回值
    • 程式執行會有兩類返回值:
      • 執行結果
      • 執行狀態返回程式碼
        • 0:正確執行
        • 1-255:錯誤執行,其中1,2,127系統預留;

4.2 如何使用shell變數

  • 引用變數方式:${VARNAME},括號有時可省略
    • 不能省略的情況:當有引起變數名混淆的情況時,必須加括號來幫助直譯器識別變數的邊界。

4.3 命令替換中使用變數替換

在命令替換中使用變數替換,也就是在命令替換中使用變數

  • 命令替換`` 輸入的是命令,拿到的是命令執行的結果
  • 在字串操作中涉及變數替換時,需注意:
    • 單引號是強引用,不做變數替換
    • 雙引號是弱引用,可做變數替換

5.涉及到shell變數的相關操作

5.1 set用來定義變數

  • 定義格式:set VARNAME
    set可省略,所以set來定義變數是一個很雞肋的用法,我們基本不用
    set 可省略

5.2 撤銷變數

  • 可撤銷環境變數和本地變數(區域性變數)
  • 撤銷格式:unset VARNAME ps:不需要加$

5.3 檢視變數

  • 檢視當前shell中所有變數(包括環境變數和本地變數)
    • 命令:set
  • 檢視當前shell中的環境變數:
    • 命令:printenv
    • 命令:env
    • 命令:export

5.4 字串變數進行拼接

拼接示例方法如下:

ANIMALS=pig
ANIMALS=$ANIMALS:sheep
  • 對shell來講預設所有的值都是字串,預設不能做算術運算

6.shell指令碼

6.1 什麼是指令碼?

指令碼:是命令的堆砌,按實際需要,結合命令流程控制機制實現的源程式

6.2 shell指令碼的格式要求

  • 在shell指令碼的開頭要加上#!/bin/bash
    因為Linux核心只能理解ELF檔案,只有檔案中加上shebang:魔數magic num也就是#!/bin/bash
  • 想要執行的話,需要加執行許可權,不想加許可權的話也可以用bash SCRIPTNAME.sh的方式來執行

6.3 shell指令碼的注意方法

  • 單行註釋:以#開頭的行就是註釋,會被直譯器忽略
  • 多行註釋:
:<<EOF
註釋內容...
註釋內容...
註釋內容...
EOF

EOF也可以使用其他符號:

:<<`
註釋內容...
註釋內容...
註釋內容...
`
:<<!
註釋內容...
註釋內容...
註釋內容...
!

相關文章