天天看點

Linux 上 Bash 的基礎特性

版權聲明:本文為部落客原創文章,轉載請注明出處。 https://blog.csdn.net/gongxifacai_believe/article/details/83383829

1、指令曆史

shell程序會在其會話中儲存此前使用者送出執行過的指令。

(1)

~]# history

定制history的功能,可通過環境變量實作:

1)HISTSIZE:shell程序可保留的指令曆史的條數;

2)HISTFILE:持久儲存指令曆史的檔案;

3).bash_history:使用者登出時儲存指令曆史的檔案(使用者家目錄下的隐藏檔案)。每次使用者登入,将.bash_history檔案中的指令加載到記憶體中,之後在shell中執行history,顯示的是記憶體中的指令,包括登入時加載的.bash_history指令和剛剛輸入的指令。cat .bash_history 顯示的是.bash_history中的指令,沒有剛剛輸入的指令,因為隻有在使用者登出時才将剛剛輸入的指令儲存到.bash_history檔案中。

4)HISTFILESIZE:指令曆史檔案的大小。

指令用法:

(2)

history [-c] [-d 偏移量] [n] 操作檔案

history -anrw [檔案名]

history -ps 參數 [參數...]

-c: 清空指令曆史;

-d offset:删除指定指令曆史;

(3)

history -d offset n

:從指令編号為offset開始删除n條;

-r:從檔案讀取指令曆史至曆史清單中;

-w:把曆史清單中的指令追加至曆史檔案中;

(4)

history #

:顯示最近的#條指令;

(5)調用指令曆史清單中的指令:

!#:再一次執行曆史清單中的第#條指令;

!!:再一次執行上一條指令;

!STRING:再一次執行指令曆史清單中最近一個以STRING開頭的指令;

注意:指令的重複執行有時候需要依賴于幂等性;

(6)調用上一條指令的最後一個參數:

快捷鍵:ESC, . (ESC松開後再按.)

快捷鍵:Alt+. (按住Alt再按.)

字元串:!$ (直接輸入!$)

需要注意的是:連續執行相同的指令,在曆史記錄裡面隻記錄一次。

(7)控制指令曆史記錄的方式:

環境變量:

HISTCONTROL

(在/etc/profile配置檔案中控制)

ignoredups:忽略重複的指令,連續且相同方為“重複”;

ignorespace:忽略以空白字元開頭的指令;

ignoreboth:以上兩者同時生效;

修改變量的值:NAME=‘VALUE’

eg.

HISTCONTROL=ignorespace

,該修改僅對目前shell程序有效。

環境變量修改永久生效:export 變量名=“值”

2、指令操作

(1)指令補全

shell程式在接收到使用者執行指令的請求,分析完成之後,最左側的字元串會被當作指令。

指令查找機制:

  1. 查找内部指令;
  2. 查找外部指令:根據PATH環境變量中設定的目錄,自左而右逐個搜尋目錄下的檔案名。

給定的打頭字元串如果能惟一辨別某指令程式檔案,則直接補全;不能惟一辨別某指令程式檔案,再擊tab鍵一次,會給出清單。

(2)路徑補全

在給定的起始路徑下,以對應路徑下的打頭字串來逐一比對起始路徑下的每個檔案。

如果能惟一辨別,則直接補全;否則,再一次tab,給出清單。

(3)指令行展開

~:自動展開為使用者的家目錄,或指定的使用者的家目錄;

{}:可承載一個以逗号分隔的路徑清單,并能夠将其展開為多個路徑;

例如:

/tmp/{a,b}

相當于

/tmp/a /tmp/b

(4)指令的執行狀态結果

bash通過狀态傳回值來輸出此結果:成功傳回0,失敗傳回1-255之間的值。

指令執行完成之後,其狀态傳回值儲存于bash的特殊變量

$?

中。

指令正常執行時,有的還會有指令傳回值,根據指令及其功能不同,結果各不相同。

引用指令的執行結果:

$(COMMAND)

COMMAND

3、引用

強引用:’ ',其中任何内容直接顯示,不做替換。

弱引用:" ",其中變量做變量替換,将出現變量的地方替換成變量的值。

指令引用:``

4、快捷鍵

Ctrl+a

:跳轉至指令行行首;

Ctrl+e

:跳轉至指令行行尾;

Ctrl+u

:删除行首至光标所在處之間的所有字元;

Ctrl+k

:删除光标所在處至行尾的所有字元;

Ctrl+l

:清屏,相當于clear;

Ctrl+c

:取消指令的執行;

5、globbing

globbing用于檔案名通配,是整體檔案名比對,而非部分檔案名比對。

比對模式

(1)* :比對任意長度的任意字元;

例:pa*, * pa *, * pa, *p * a *

(2)?:比對任意單個字元;

例:pa?, ??pa, p?a, p?a?

(3)[]:比對指定範圍内的任意單個字元;

有幾種特殊格式:

1)[a-z], [A-Z], [0-9], [a-z0-9];

2)[[:upper:]]:所有大寫字母;

3)[[:lower:]]:所有小寫字母;

4)[[:alpha:]]:所有字母;

5)[[:digit:]]:所有數字;

6)[[:alnum:]]:所有的字母和數字;

7)[[:space:]]:所有空白字元;

8)[[:punct:]]:所有标點符号;

(4)[^]:比對指定範圍外的任意單個字元;

例:[ ^ [:upper:]],[ ^ 0-9],[ ^ [:alnum:]];

例1:顯示/var目錄下所有以l開頭,以一個小寫字母結尾,且中間出現一位任意字元的檔案或目錄:

ls -d /var/l?[[:lower:]]

例2:顯示/etc目錄下,以任意一位數字開頭,且以非數字結尾的檔案或目錄:

ls -d /etc/[0-9]*[^0-9]

例3:顯示/etc目錄下,以非字母開頭,後面跟一個字母及其它任意長度任意字元的檔案或目錄:

ls -d /etc/[^a-z][a-z]*

例4:複制/etc目錄下,所有以m開頭,以非數字結尾的檔案或目錄至/tmp/magedu.com目錄:

cp -r /etc/m*[^0-9] /tmp/magedu.com/

例5:複制/usr/share/man目錄下,所有以man開頭,後跟一個數字結尾的檔案或目錄至/tmp/man/目錄下:

cp -r /usr/share/man/man[0-9] /tmp/man/

例6:複制/etc目錄下,所有以.conf結尾,且以m,n,r,p開頭的檔案或目錄至/tmp/conf.d/目錄下:

cp -r /etc/[mnrp]*.conf /tmp/conf.d/

6、IO重定向

(1)可用于輸入的裝置:鍵盤裝置、檔案系統上的正常檔案、網卡等;

可用于輸出的裝置:顯示器、檔案系統上的正常檔案、網卡等;

(2)程式的資料流有三種:

輸入的資料流 <-- 标準輸入(stdin)(鍵盤);

輸出的資料流 --> 标準輸出(stdout)(顯示器);

錯誤輸出流 --> 錯誤輸出(stderr)(顯示器);

标準輸入用0表示,标準輸出用1表示,錯誤輸出用2表示。

(3)IO重定向

輸出重定向:>

(特性:覆寫輸出)

輸出重定向:>>

(特性:追加輸出)

輸入重定向:<

Here Document:<< 此處建立文檔,把所輸入的内容建立為文檔。

(4)輸出重定向

set指令:

設定或撤銷shell選項的值和位置參數

# set -C

禁止覆寫輸出重定向至已存在的檔案,該指令僅對目前shell程序有效,此時可使用強制覆寫輸出:>|。

# set +C

關閉上述特性。

錯誤輸出流重定向:2>, 2>>

例:

[root@localhost exercise]# cat /etc/issue1 2> issue1.err

合并正常輸出流和錯誤輸出流:

1)&>, &>>

例:

cat /etc/fstab3 &> fstab3.out

2)COMMAND > /path/to/somefile 2>&1 覆寫輸出

COMMAND >> /path/to/somefile 2>>&1 追加輸出

例:

cat /etc/rc.d/init.d/functions2 >> function.out 2>&1

特殊裝置:/dev/null 資料黑洞

[root@localhost exercise]# ls /varr &> /dev/null
[root@localhost exercise]# echo $?
2
[root@localhost exercise]# ls /var &> /dev/null
[root@localhost exercise]# echo $?
0
對輸出結果不關心,關心指令的狀态結果           

複制

(5)輸入重定向:<

tr指令:

tr [OPTION]... SET1 [SET2]

把輸入的資料當中的字元,凡是在SET1定義範圍内出現的,通通對位轉換為SET2出現的字元。

1)用法1:

tr SET1 SET2 < /PATH/FROM/SOMEFILE

将SOMEFILE中SET1中出現的字元替換成SET2,并輸出至螢幕(SOMEFILE原檔案不改變)。

2)用法2:

tr -d SET1 < /PATH/FROM/SOMEFILE

從SOMEFILE中移除SET1中的字元,并輸出至螢幕(SOMEFILE原檔案不改變)。

注意:不修改原檔案。

[root@localhost exercise]# tr [a-z] [A-Z]
how are you?
HOW ARE YOU?				
[root@localhost exercise]# tr [a-z] [A-Z] < /etc/issue
\S
KERNEL \R ON AN \M				
[root@localhost exercise]# tr -d 'abc' < /etc/issue
\S
Kernel \r on n \m				
[root@localhost exercise]# tr -d '[A-Z]' < /etc/issue
\S
ernel \r on n \m
[root@localhost exercise]# cat /etc/issue
\S
Kernel \r on an \m

把/etc/passwd檔案的前6行的資訊轉換為大寫字元後輸出:
head -n 6 /etc/passwd | tr 'a-z' 'A-Z'
或者:[root@localhost exercise]# cat /etc/passwd | head -6 |tr 'a-z' 'A-Z'           

複制

(6)Here Document:<< 此處建立文檔,把所輸入的内容建立為文檔

cat << EOF EOF為結束符

cat > /PATH/TO/SOMEFILE << EOF

[root@localhost exercise]# cat << EOF
> how are you?
> what are you doing?
> EOF
how are you?
what are you doing?
[root@localhost exercise]# cat > cat.out <<END
> how are you?
> what are you doing?
> END
[root@localhost exercise]# cat cat.out
how are you?
what are you doing?           

複制

7、管道

管道:連接配接程式,實作将前一個指令的輸出直接定向後一個程式當作輸入資料流,前一個指令的輸出作為後一個指令的輸入。

COMMAND1 | COMMAND2 | COMMAND3 | ...

[root@localhost exercise]# cat /etc/issue | tr 'a-z' 'A-Z'
\S
KERNEL \R ON AN \M						 
[root@localhost exercise]# who
root     :0           2016-11-16 07:21 (:0)
root     pts/0        2016-11-16 07:21 (:0)
root     tty2         2016-11-16 07:25
[root@localhost exercise]# who | head -2
root     :0           2016-11-16 07:21 (:0)
root     pts/0        2016-11-16 07:21 (:0)
[root@localhost exercise]# who | head -2 | tr 'a-z' 'A-Z'
ROOT     :0           2016-11-16 07:21 (:0)
ROOT     PTS/0        2016-11-16 07:21 (:0)
[root@localhost exercise]# who | head -2 | tr 'a-z' 'A-Z' | tr -d '0-9'
ROOT     :           -- : (:)
ROOT     PTS/        -- : (:)           

複制

(1)tee指令

從标準輸入讀入,并寫往标準輸出和檔案。

COMMAND | tee /PATH/TO/SOMEFILE

[root@localhost exercise]# cat /etc/issue | tee issue.tee | tr 'a-z' 'A-Z'
\S
KERNEL \R ON AN \M
[root@localhost exercise]# cat issue.tee
\S
Kernel \r on an \m           

複制

8、指令hash

(1)hash的作用

hash就是記錄或顯示程式的位置(可執行程式的位置)。如果我們執行程式,系統每次都要從目錄裡面查找可執行檔案,如果目錄裡面有很多可執行程式,那每次都需要花費很多時間去找檔案,這就勢必導緻系統響應很慢,當然這也很不現實。實際中是隻有第一次才去完整查找指令執行檔案的,然後将其查詢的結果記錄下來放置到緩存中,如果下次還需要執行同樣的指令,那麼就直接從緩存中找指令的執行檔案,然後直接執行。

這個緩存就是一個key/value的存儲,可以通過hash指令來檢視這個指令的緩存結果,這裡的value就是指令的可執行檔案的路徑,key是一段hash碼。

将一個指令移入到另一個目錄裡面來執行該指令,如:mv /bin/ls /usr/bin/ls,再執行ls指令,會發現系統找不到ls指令了。

(2)hash的使用

hash:列出hash緩存,緩存此前指令的查找結果:key-value,key為搜尋鍵,value為值;

通過内部指令擷取幫助資訊的方式來擷取hash指令的使用方法:

help hash

hash -d COMMAND:删除hash中的某一條指令,COMMAND不需要給完整路徑,隻需要給指令名稱即可;

hash -r:清空hash緩存。

[root@localhost ~]# hash
hits	command
1	/usr/bin/grep
1	/usr/bin/ls
[root@localhost ~]# hash -d ls
[root@localhost ~]# hash
hits	command
 1	/usr/bin/grep
[root@localhost ~]# hash -r
[root@localhost ~]# hash
hash: hash table empty           

複制

9、變量

(1)變量類型定義了資料存儲格式、存儲空間大小、參與的運算種類、表示的資料範圍等。變量有強類型和弱類型。強類型是指定義變量時必須指定類型、參與運算必須符合類型要求,如果調用未聲明變量的,則會産生錯誤。弱類型是指無需指定類型,預設均為字元型,參與運算會自動進行隐式類型轉換,變量無需事先定義可以直接調用。bash就屬于弱類型的程式設計語言。

變量的類型有:字元型、數值型。數值型又分為整型和浮點型。

bash是弱類型語言,把所有變量統統視作字元型,當我們強行指明做數值加減運算時,可以轉換為數值型。bash不支援浮點資料,除非我們借助外在工具。

變量聲明:bash中的變量無需事先聲明,相當于把聲明和指派過程同時實作。

變量替換:把變量名出現的位置替換為其所指向的記憶體空間中資料。

變量引用:${var_name}, $var_name

變量名:變量名隻能包含數字、字母和下劃線,而且不能以數字開頭。

變量名:見名知義,命名機制遵循某種法則,不能夠使用程式的保留字,例如if, else, then, while等等。

shell可以有子shell,子shell又可以有子shell,并且父shell和子shell的shell類型可以不同(如,父shell為bash,子shell為csh),使用exit退出目前shell,回到父shell。

(2)bash變量類型

本地變量:作用域僅為目前shell程序;

環境變量:作用域為目前shell程序及其子程序;

局部變量:作用域僅為某代碼片斷(函數上下文);

位置參數變量:向執行腳本的shell程序傳遞的參數;

特殊變量:shell内置的有特殊功用的變量;如 $ ?,用于表示指令執行的狀态結果,0表示成功,1-255表示失敗。

(3)本地變量

生效範圍為目前shell程序,對目前shell之外的其他shell程序,包括目前shell的子shell程序均無效。

變量指派:name=‘value’,其中value可以是直接字元串:name=“username”,變量引用:name="$username",也可以是指令引用:name=COMMAND(反引号),name= $(COMMAND)。

變量引用: $ name,$ {name}

“ ”:弱引用,其中的變量引用會被替換為變量值;

’ ':強引用,其中的變量引用不會被替換為變量值,而保持原字元串。

顯示已定義的所有變量:set,CentOS6和CentOS7執行set不同,CentOS7會顯示shell内置的函數;

撤銷變量:unset name;注意:此處非變量引用;不加 $。

[root@localhost ~]# first_name=jerry
[root@localhost ~]# echo $first_name
jerry
[root@localhost ~]# unset first_name
[root@localhost ~]# echo $first_name

[root@localhost ~]#            

複制

(4)環境變量:變量作用域可以用于子shell,可以多級繼承

變量指派:

1)export name=value
2)name=value
export name
3)declare -x name=value     declare是bash内嵌指令,可以導出變量;
4)name=value
declare -x name
declare -i name              聲明整型變量(bash數值型變量隻支援整型,不支援浮點型)           

複制

變量引用:${name}, $name

bash内嵌了許多環境變量(通常為全大寫字元),用于定義bash的工作環境:

PATH, HISTFILE, HISTSIZE, HISTFILESIZE, HISTCONTROL, SHELL, HOME, UID, PWD, OLD, OLDPWD, PS1等。

檢視環境變量:

export, declare -x, printenv, env

撤銷環境變量:

unset name

隻讀變量:

1)declare -r name
2)readonly name           

複制

隻讀變量無法重新指派,并且不支援撤銷,存活時間為目前shell程序的生命周期,随shell程序終止而終止。

(5)局部變量:生效範圍為目前shell程序中的某代碼片段(通常指函數)。

(6)位置變量:$ 1,…,$ n,$ {10}來表示,用于在腳本代碼中調用通過指令行傳遞給它的參數。

(7)特殊變量

$?:上個指令執行成功與否的結果;

$0:表示指令本身;

$#:傳遞給腳本參數的個數;

$*:傳遞給腳本的所有參數;

$@:引用傳遞給腳本的所有參數。

10、多指令執行

~]# COMMAND1; COMMAND2; COMMAND3; ...

11、邏輯運算

短路法則:

~]# COMMAND1 && COMMAND2

COMMAND1為“假”,則COMMAND2不會再執行,否則,COMMAND1為“真”,則COMMAND2必須執行。

~]# COMMAND1 || COMMAND2

COMMAND1為“真”,則COMMAND2不會再執行,否則,COMMAND1為“假”,則COMMAND2必須執行。

[root@localhost ~]# touch /tmp/test.etc && ls /etc > /tmp/test.etc
[root@localhost ~]# touchabc /tmp/test.etc2 && ls /etc > /tmp/test.etc2
bash: touchabc: command not found...
[root@localhost ~]# cat /tmp/test.etc2
cat: /tmp/test.etc2: No such file or directory

~]# id $username || useradd $username       如果username不存在,則建立他
[root@localhost ~]# id user1
id: user1: no such user
[root@localhost ~]# id user1 || useradd user1
id: user1: no such user
[root@localhost ~]# id user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)
[root@localhost ~]# id user1 || useradd user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)           

複制

12、bash的配置檔案

(1)bash配置檔案的分類

bash的配置檔案分為兩類:

profile類:為互動式登入的shell程序提供配置;

bashrc類:為非互動式登入的shell程序提供配置。

(2) shell程序的分類

按照登入類型将shell程序分為兩類:互動式登入shell程序和非互動式登入shell程序。

互動式登入shell程序:

1)直接通過某終端輸入賬号和密碼後登入打開的shell程序;

2)使用su指令:su - USERNAME, 或者使用 su -l USERNAME執行的登入切換。

非互動式登入shell程序:

1)su USERNAME執行的登入切換;

2)圖形界面下打開的終端;

3)通過運作腳本,shell腳本的運作是通過運作一個子shell程序實作的。

(3)profile類配置檔案

全局配置檔案(對所有使用者都生效):

/etc/profile 主配置檔案

/etc/profile.d/* .sh 配置檔案片段

使用者個人配置檔案(僅對目前使用者有效):

~/.bash_profile

profile類配置檔案功用:

1)用于定義環境變量;

2)運作指令或腳本。

(4)bashrc類配置檔案

全局配置檔案(對所有使用者都生效):

/etc/bashrc

使用者個人配置檔案(對某一使用者生效):

~/.bashrc

bashrc配置檔案功用:

1)定義本地變量;

2)定義指令别名。

僅管理者可修改全局配置檔案,普通使用者沒有權限編輯。

(5) 配置檔案的讀取順序

互動式登入shell程序:

直接通過終端輸入賬号和密碼登入,或者使用su -l USERNAME或su - USERNAME切換登入使用者:

/etc/profile --> /etc/profile.d/* .sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

非互動式登入shell程序:

使用su USERNAME或者圖形界面下打開的終端,執行腳本

~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh

(6)配置檔案的生效

指令行中定義的特性,例如變量和别名作用域為目前shell程序的生命周期。

配置檔案定義的特性,隻對随後新啟動的shell程序有效。

讓通過配置檔案定義的特性立即生效:

1)退出并重新登入;

2)讓shell程序重讀配置檔案;

~]# source /PATH/FROM/CONF_FILE
~]# .  /PATH/FROM/CONF_FILE         .的意思就是source指令           

複制

(7)設定使用者登入歡迎語句

[root@localhost exercise]# nano /etc/profile.d/welcome.sh
welcome.sh檔案内容:
echo "Welcome aboard..."           

複制

不需要賦予權限,下次登入時即可加載該配置檔案,全部使用者登入時都可看到歡迎語句。