Shell學習筆記(一)

一、相關概述

1、圖形界面和命令行要達到的目的是一樣的,都是讓用戶控制計算機。然而,真正能夠控制計算機硬件(CPU、內存、顯示器等)的只有操作系統內核(Kernel),圖形界面和命令行只是架設在用戶和內核之間的一座橋樑。

2、用戶不能直接接觸內核,這時候需要開發一個程序作爲中間代理,將用戶的操作需求轉化爲內核能接受的信息進行傳入,而用戶界面和命令行就是充當這個中間代理角色的程序。在Linux下,這個命令行就叫做Shell。

3、Shell也是一種編程語言,它的編譯器(解釋器)就是Shell這個程序,我們平時所說的Shell,有時是指連接用戶和內核的這個程序,有時又是指Shell編程。

4、任何代碼最終都要被“翻譯”成二進制的形式才能在計算機中執行。有的編程語言,如 C/C++、Pascal、Go語言、彙編等,必須在程序運行之前將所有代碼都翻譯成二進制形式,也就是生成可執行文件,用戶拿到的是最終生成的可執行文件,看不到源碼,這個過程叫做編譯,這樣的編程語言叫做編譯型語言,完成編譯過程的軟件叫做編譯器。而有的編程語言,如 Shell、JavaScript、Python、PHP等,需要一邊執行一邊翻譯,不會生成任何可執行文件,用戶必須拿到源碼才能運行程序。程序運行後會即時翻譯,翻譯完一部分執行一部分,不用等到所有代碼都翻譯完,這個過程叫做解釋,完成解釋過程的軟件叫做解釋器。

補充:編譯型語言的優點是執行速度快、對硬件要求低、保密性好,適合開發操作系統、大型應用程序、數據庫等。腳本語言的優點是使用靈活、部署容易、跨平臺性好,非常適合Web開發以及小工具的製作。

二、常見的Shell

1、sh

sh 的全稱是 Bourne shell,由 AT&T 公司的 Steve Bourne開發,爲了紀念他,就用他的名字命名了。sh 是 UNIX 上的標準 shell,很多 UNIX 版本都配有 sh。sh 是第一個流行的 Shell。

2、csh

sh 之後另一個廣爲流傳的 shell 是由柏克萊大學的 Bill Joy 設計的,這個 shell 的語法有點類似C語言,所以才得名爲 C shell ,簡稱爲 csh。Bill Joy 是一個風雲人物,他創立了 BSD 操作系統,開發了 vi 編輯器,還是 Sun 公司的創始人之一。BSD 是 UNIX 的一個重要分支,後人在此基礎上發展出了很多現代的操作系統,最著名的有 FreeBSD、OpenBSD 和 NetBSD,就連 Mac OS X 在很大程度上也基於BSD。

3、tcsh

tcsh 是 csh 的增強版,加入了命令補全功能,提供了更加強大的語法支持。

4、ash

一個簡單的輕量級的 Shell,佔用資源少,適合運行於低內存環境,但是與下面講到的 bash shell 完全兼容。

5、bash

bash shell 是 Linux 的默認 shell,本教程也基於 bash 編寫。bash 由 GNU 組織開發,保持了對 sh shell 的兼容性,是各種 Linux 發行版默認配置的 shell。

6、查看當前系統支持的sh
$ cat /etc/shells

7、查看當前系統默認使用的sh
$ echo $SHELL

三、Hello示例

1、新建腳本文件,後綴隨意,見名知意即可,eg : test.sh;

2、編輯內容如下:

#!/bin/bash
#聲明本腳本使用的解釋器

# Copyright (c) http://c.biancheng.net/shell/

#輸出文字
echo "What is your name?"

#讀取用戶輸入,並將用戶輸入內容賦值給PERSON變量
read PERSON

#輸入變量內容
echo "Hello, $PERSON"

3、Shell腳本執行:

$ cd demo  #切換到 test.sh 所在的目錄
$ chmod +x ./test.sh  #使腳本具有執行權限
$ ./test.sh  #執行腳本

補充:使用點號“.”即使沒有可執行權限依然能夠運行。

四、基本語法

1、變量

a. 變量不需要指明類型,直接賦值即可,也可以使用declare關鍵字顯示定義變量的類型;

b. 變量定義方式:單引號、雙引號、都不帶;

c. 賦值號=的周圍不能有空格;

d. 命名規則和大部分編程語言一致;

e. 變量輸出時,需要在變量名前加$,而花括號{}可加可不加,加爲了區分邊界;

f. 只讀變量聲明:readonly;

g. 刪除變量:unset variable_name

單引號和雙引號的區別:前者原樣輸出內容,而後者存在變量是支持解釋。

2、變量的作用域(Scope)

  • 有的變量可以在當前 Shell 會話中使用,這叫做全局變量(global variable);
  • 有的變量只能在函數內部使用,這叫做局部變量(local variable);
  • 有的變量還可以在其它 Shell 中使用,這叫做環境變量(environment variable)。

全局變量:當前會話有效,聲明方式可以使用命令行直接聲明,或者在腳本中聲明。聲明的變量在同一會話下都有效。

局部變量:腳本文件內的函數定義的變量,默認也是全局變量,只有在變量前顯示使用local進行聲明纔是局部變量。

環境變量: 使用export關鍵字將變量導出,定義的變量在字Shell中也有效,但是關閉Shell會話後它就自動銷燬。永久保留的方式是把環境變量寫入啓動文件。

3、給腳本傳遞位置參數

腳本test.sh代碼如下:

#!/bin/bash

echo "Language: $1"
echo "URL: $2"

運行test.sh,並附帶參數:

$ . ./a.sh Shell http://c.biancheng.net/shell/

4、給函數傳遞位置參數
腳本test.sh代碼如下:

#!/bin/bash
#定義函數
function func(){
    echo "Language: $1"
    echo "URL: $2"
}
#調用函數
func C++ http://c.biancheng.net/cplus/

執行test.sh:

$. ./test.sh

5、特殊變量

變量 含義
$0 當前腳本的文件名。
$n(n≥1) 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是 $1,第二個參數是 $2。
$# 傳遞給腳本或函數的參數個數。
$* 傳遞給腳本或函數的所有參數。
$@ 傳遞給腳本或函數的所有參數。當被雙引號" "包含時,$@ 與 $* 稍有不同,我們將在《Shell *和@的區別》一節中詳細講解。
$? 上個命令的退出狀態,或函數的返回值,我們將在《Shell $?》一節中詳細講解。
$$ 當前 Shell 進程 ID。對於 Shell 腳本,就是這些腳本所在的進程 ID。

*與@區別:當被“”包圍時,前者將所有的參數從整體上看做是一份數據,而不是把每一個參數都看做一份數據,for循環時,只循環一遍,而後者則將每一個參數作爲一份數據,彼此之間獨立。

6、Shell命令替換: 理解爲將指令的執行結果賦值給變量

示例:

#方式一:使用反應號將指令包圍
var_name1 = `date`

#方式二:使用$()將指令包圍
var_name2 = $(date)

echo $var_name1
echo $var_name2

注意:變量輸出時,不使用“”包圍的話,換行符、連續空白等格式都將會被壓縮成一個空格,而使用“”包圍則會按照原樣格式進行輸出。

7、字符串

  • 由單引號’ '包圍的字符串:任何字符都會原樣輸出,在其中使用變量是無效的,而且字符串中不能出現單引號,轉義也不行;
  • 由雙引號包圍的字符串:如若其中包含變量,變量會自動解析,字符串中可以包含雙引號,但需要轉義;
  • 不被引號包圍:出現變量依然能被解析,但是字符串中不能出現空格,否則空格之後的將會作爲新的變量進行處理。

獲取字符串的長度:

#!/bin/bash

str="http://c.biancheng.net/shell/"

echo ${$str}

**字符串連接:**直接將變量並在一起即可

#!/bin/bash

#全是變量
name="Shell"
url="http://c.bian.com"
str1=$name$url #沒被任何一種引號包圍時,不能有空格,否則被誤認爲字符串結束
str2="$name $url" #中間允許有空格
#非全變量
str3=$name":"$url #中間允許其他符號
str4="${name}Script:${url}index.html"

echo $str1
echo $str2
echo $str3
echo $str4

字符串截取:

(1)從指定位置開始截取

#!/bin/bash

url="c.biancheng.net"

#從左邊開始計數
echo ${url:2:9} #從第2個字符開始,截取九個長度的字符串
echo ${url:2} #從第2個字符開始,截取到末尾

#從右邊開始計數
echo ${url:0-13:9}
echo ${url:0-13} #截取到末尾

(2)從指定字符串開始截取

特點:這種截取方式無法指定字符串的長度,只能從指定字符開始截到末尾,但可以選擇右邊所有字符或者左邊所有字符

使用#截取右邊所有字符:從左往右

#!/bin/bash

url="http://test.com"
#使用#指定獲取字符右邊的所有字符,其中*是表示忽略左邊的字符
echo ${url#*:} #結果輸出://test.com
echo ${url#:} #結果輸出:http://test.com

#使用#默認匹配從左往右首個匹配到的字符,若要匹配最後一個匹配的字符,則使用兩個#
url="http://test.com/index.html"
echo ${url#*/} #結果輸出:/test.com/index.html
echo ${url##*/} #結果輸出:index.html

使用%截取左邊所有字符:從右往左

#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url%/*}  #結果爲 http://c.biancheng.net
echo ${url%%/*}  #結果爲 http:
str="---aa+++aa@@@"
echo ${str%aa*}  #結果爲 ---aa+++
echo ${str%%aa*}  #結果爲 ---

兩者用法一致,方向相反而已。

8、Shell數組:

Shell並沒有限制數組的大小,理論上可以存放無限量的數據。數組元素的下標也是從0開始計數,獲取數組中的元素要使用下標[]。常用的Bash Shell只支持以爲數組,不支持多爲數組。

數組定義

#數組元素之間使用空格分隔,數組元素不要求類型相同
num=(20 39 49 55 "http://test.com")

#追加元素
num[5]=88

#給指定元素賦值
ages=([3]=23 [5]=19 [10]=12)

獲取數組元素

#獲取單個元素值
n=${nums[2]}

#獲取所有元素值
${nums[*]}
${nums[@]}

nums=(29 100 13 8 91 44)
echo ${nums[@]}  #輸出所有數組元素
nums[10]=66  #給第10個元素賦值(此時會增加數組長度)
echo ${nums[*]}  #輸出所有數組元素
echo ${nums[4]}  #輸出第4個元素

運行結果:
29 100 13 8 91 44
29 100 13 8 91 44 66
91

獲取數組長度

使用@或者*,可以將數組擴展成爲列表,然後使用#來獲取數組的個數:

#!/bin/bash

nums=(29 100 13)
echo ${#nums[*]}

#向數組中添加元素
nums[10]="http://c.biancheng.net/shell/"
echo ${#nums[@]}
echo ${#nums[10]}

#刪除數組元素
unset nums[1]
echo ${#nums[*]

運行結果:
3
4
29
3

數組拼接

拼接數組的思路是:先利用@或*,將數組擴展成列表,然後再合併到一起。示例如下:

#!/bin/bash

array1=(23 56)
array2=(99 "http://c.biancheng.net/shell/")

array_new=(${array1[@]} ${array2[*]})
echo ${array_new[@]}  #也可以寫作 ${array_new[*]}

#運行結果:
#23 56 99 http://c.biancheng.net/shell/

刪除數組

在 Shell 中,使用 unset 關鍵字來刪除數組元素,具體示例如下:

#!/bin/bash

arr=(23 56 99 "http://c.biancheng.net/shell/")

unset arr[1]
echo ${arr[@]}

unset arr
echo ${arr[*]}

#運行結果:
#23 99 http://c.biancheng.net/shell/
#

9、Shell內建指令(內置指令)

所謂 Shell 內建命令,就是由 Bash 自身提供的命令,而不是文件系統中的某個可執行文件。

10、Shell alias:給命令創建別名

查看那些指令被默認創建了別名;

[root@localhost ~]# alias
alias cp='cp -i'
alias l.='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias ls='ls --color=tty'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

自定義別名:使用 alias 定義的別名命令也是支持 Tab 鍵補全的

alias myShutdown='shutdown -h now'

注意,這樣定義別名只能在當前 Shell 環境中有效,換句話說,重新登錄後這個別名就消失了。爲了確保永遠生效,可以將該別名手動寫入到用戶主目錄中的.bashrc文件。

.bashrc其實也是一個 Shell 腳本文件,該文件專門用來存放用戶自定義的別名和函數。

將別名寫入.bashrc文件後的效果如下所示:

# .bashrc
# User specific aliases and functions

alias myShutdown='shutdown -h now'

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

unalias:刪除別名

使用 unalias 內建命令可以刪除當前 Shell 環境中的別名。unalias 有兩種使用方法:

  • 第一種用法是在命令後跟上某個命令的別名,用於刪除指定的別名。
  • 第二種用法是在命令後接-a參數,刪除當前 Shell 環境中所有的別名。

同樣,這兩種方法都是在當前 Shell 環境中生效的。要想永久刪除在.bashrc文件中定義的別名,只能進入該文件手動刪除。

11、echo命令

(1)添加-n參數不換行;

(2)添加-e參數顯示轉義字符;

(3)添加-e參數,配合\c轉義字符強制不換行;

12、exit命令

(1)腳本內執行exit,結束代碼運行,退出Shell腳本;

(2)終端執行exit,退出當前登錄的Shell,並結束終端;

13、Shell ulimit命令:顯示並設置進程資源限度

系統的可用資源是有限的,如果不限制用戶和進程對系統資源的使用,則很容易陷入資源耗盡的地步,而使用 ulimit 命令可以控制進程對可用資源的訪問(ulimit 是一個 Shell 內置命令)。

默認情況下 Linux 系統的各個資源都做了軟硬限制,其中硬限制的作用是控制軟限制(換言之,軟限制不能高於硬限制)。使用ulimit -a可以查看當前系統的軟限制,使用命令ulimit -a –H可查看系統的硬限制。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章