天天看點

bash常用特性之一

Bash介紹:

Bash(GNU Bourne-Again SHell)是許多Linux平台的内定Shell,事實上,還有許多傳統UNIX上用的Shell,像tcsh、csh、ash、bsh、ksh等等,Shell Script大緻都類同,當您學會一種Shell以後,其它的Shell會很快就上手,大多數的時候,一個Shell Script通常可以在很多種Shell上使用

BASH的正确縮寫:

BASH = GNU Bourne-Again SHell,BASH 是 GNU 組織開發和推廣的一個項目。

BASH的作者和産生:

Bourne shell 的作者是 Steven Bourne,它是 UNIX 最初使用的 Shell 并且在每種 UNIX 上都可以使用。

而BASH 與 Bourne shell 完全向後相容,是Bourne shell的擴充。

bash 内置特性

檔案名通配:globbing

Bash本身沒有正規表達式的功能,在腳本裡,使用正規表達式的是指令和軟體包

例如sed和awk,它們可以解釋正規表達式.

Bash所做的是展開檔案名擴充 -- 這就是所謂的通配(globbing) -- 但它不是使用标準的正規表達式. 而是使用通配符. 通配解釋标準的通配符:*和?, 方括号括起來的字元,還有其他的一些特殊的字元(比如說^用來表示取反比對).然而通配機制的通配符有很大的局限性. 包含有*号的字元串将不會比對以點開頭的檔案,例如.bashrc. 另外,通配機制的? 字元和正規表達式中表示的意思不一樣.

看圖說話:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code>#在script建立了五個檔案</code>

<code>[root@localhost script]</code><code># touch a.1 b.c c.c t2.sh test.txt</code>

<code>[root@localhost script]</code><code># ls</code>

<code>a.1  b.c  c.c  </code><code>fdisk</code><code>.sh  </code><code>local</code><code>.sh  t2.sh  </code><code>test</code><code>.txt  tss.sh</code>

<code>[root@localhost script]</code><code># ls -l</code>

<code>total 12</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 a.1</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 b.c</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 c.c</code>

<code>-rw-r--r--. 1 root root 3126 Feb 22 00:44 </code><code>fdisk</code><code>.sh</code>

<code>-rw-r--r--. 1 root root   28 Feb 22 07:25 </code><code>local</code><code>.sh</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 t2.sh</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:18 </code><code>test</code><code>.txt</code>

<code>-rw-r--r--. 1 root root   10 Feb 22 01:39 tss.sh</code>

<code>#檢視一下script以t開頭的中間跟任一字元,以.sh結尾的檔案</code>

<code>[root@localhost script]</code><code># ls -l t?.sh</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 t2.sh</code>

15

16

17

18

19

<code>#檢視以[ab]任意一個字母開頭的檔案</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:30 abc.ddl</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:31 anb.ppt</code>

<code>-rw-r--r--. 1 root root    0 Feb 22 08:30 cvb.doc</code>

<code>[root@localhost script]</code><code># ls -l [ab]*</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 a.1</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:30 abc.ddl</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:31 anb.ppt</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 b.c</code>

<code>#非字母a或b開頭的檔案</code>

<code>[root@localhost script]</code><code># ls -l [^ab]*</code>

<code>[root@localhost script]</code><code># ls -l {b*,c*,*st*}</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 c.c</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:30 cvb.doc</code>

<code>-rw-r--r--. 1 root root 0 Feb 22 08:18 </code><code>test</code><code>.txt</code>

注:Bash會對指令行中沒有引号引起來的字元嘗試檔案名擴充

<code>[root@localhost script]</code><code># echo *</code>

<code>a.1 abc.ddl anb.ppt b.c c.c cvb.doc </code><code>fdisk</code><code>.sh </code><code>local</code><code>.sh t2.sh </code><code>test</code><code>.txt tss.sh</code>

檔案名擴充能比對點開頭的檔案,但僅在模式字串明确地包含字面意思的點(.)時才擴充.

<code>[root@localhost ~]</code><code># ls -a .bash_*</code>

<code>.bash_history  .bash_logout  .bash_profile</code>

<code>[root@localhost ~]</code><code># ls -al [?]bash_*</code>

<code>ls</code><code>: cannot access [?]bash_*: No such </code><code>file</code> <code>or directory</code>

<code>[root@localhost ~]</code><code># ls -al [.]bash_*</code>

<code>ls</code><code>: cannot access [.]bash_*: No such </code><code>file</code> <code>or directory</code>

這樣還是可以的

<code>[root@localhost ~]</code><code># ls -al .[b]?sh_profile</code>

<code>-rw-r--r--. 1 root root 176 May 20  2009 .bash_profile</code>

<code>[root@localhost ~]</code><code># ls -al .[b]?shr*</code>

<code>-rw-r--r--. 1 root root 176 Sep 22  2004 .bashrc</code>

可以改變Bash對通配字元進行解釋的行為.

set -f 指令或set -o noglob可以禁止通配機制, 并且shopt的選項nocaseglob和nullglob 能改變通配的行為.

<code>[root@localhost script]</code><code># ls a*</code>

<code>a.1  abc.ddl  anb.ppt</code>

<code>[root@localhost script]</code><code># set -f</code>

<code>ls</code><code>: cannot access a*: No such </code><code>file</code> <code>or directory</code>

這時表明通配功能己經關閉,如果要開啟,可以使用

set +o noglob

指令補全、路徑補全

Bash中的指令分為兩種,一種是bash自帶的内部指令,一種是通過環境變量讀取的可執行檔案,這個變量就是PATH,以冒号間隔的多個路徑,指令補全則是通過PATH的多路徑查找到可執行的檔案所在位置

為了簡化打字工作,bash shell 提供了幾種可以對輸入不完整的文本進行自動補全的方法,如果想對輸入進行補全,隻需輸入初始的幾個字元,然後按“Tab”鍵,系統會自動比對所需要的其餘輸入,當有多種比對時,系統會結出提示,按"ESC+?"組合鍵或按兩次"Tab"鍵,可以列出所有可能的比對,自動補全可以應用于下面的4類輸入工作之中。

環境變量名補全

<a href="http://s3.51cto.com/wyfs02/M01/18/BD/wKiom1MTEbrABCwCAADIOExJYDs838.jpg" target="_blank"></a>

如果輸入的文本以"$"開始,shell就以目前shell的環境變量補全文本

使用者名補全

如果輸入的文本以“~”開始,shell會以使用者名補全文本。

指令、别名或函數的名字補全

如果文本以正常字元開始,shell将利用指令、别名或函數名來補全文本

主機名補全

如果輸入的文本以“@”符号開始,系統會利用/etc/hosts檔案中的主機名來補全文本

<a href="http://s3.51cto.com/wyfs02/M02/18/BE/wKiom1MTEnXx9jJcAAEswoUdECs984.jpg" target="_blank"></a>

自動補全快捷鍵(此快捷鍵在遠端終端無法使用)

Alt+~  以一個使用者名補全此處文本

Alt+$ 用變量補全此處的文本

Alt+@以一個主機名補全此處文本

路徑補全

而路徑補全是在給出打頭路補全,如果沒有打頭的路徑,則視為以目前路徑開始補全。

指令曆史

Bash可以儲存過去曾經執行過的指令清單(即history 指令産生的清單),目前shell程序引用過的指令都會儲存在緩沖區中,如果有退出操作時,緩沖區中的指令會在shell退出時将以前運作過的指令儲存至檔案中(即使用者家目錄下的.bash_histor)

history 快捷方式:

!#:為指令曆史清單中的指令編号,可用執行第#條指令

!!:執行上一指令;

!- #:執行指令曆史清單中的倒數第#指令;

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

<code>[root@localhost etc]</code><code># echo "$PATH"</code>

<code>/usr/lib64/qt-3</code><code>.3</code><code>/bin</code><code>:</code><code>/usr/local/sbin</code><code>:</code><code>/usr/local/bin</code><code>:</code><code>/sbin</code><code>:</code><code>/bin</code><code>:</code><code>/usr/sbin</code><code>:</code><code>/usr/bin</code><code>:</code><code>/usr/local/axel/bin</code><code>:</code><code>/usr/local/nginx/sbin</code><code>:</code><code>/root/bin</code><code>:</code><code>/usr/local/apache/bin</code><code>:</code><code>/usr/local/apache/bin</code><code>:</code><code>/usr/local/axel/bin</code><code>:</code><code>/usr/local/nginx/sbin</code>

<code>[root@localhost etc]</code><code># !e</code>

<code>echo</code> <code>"$PATH"</code>

!$:引用上一個指令的最後一個參數;(也可以使用按下esc,之後按一下.)

history

-c: 清空清單

<code>[root@localhost etc]</code><code># history  |tail -5</code>

<code>  </code><code>119  </code><code>history</code> <code>-d 199</code>

<code>  </code><code>120  </code><code>history</code> <code>-d 119</code>

<code>  </code><code>121  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>  </code><code>122  </code><code>history</code> <code>-d 118</code>

<code>  </code><code>123  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>[root@localhost etc]</code><code># history -c</code>

<code>[root@localhost etc]</code><code># history</code>

<code>    </code><code>1  </code><code>history</code>

-d #: 删除指定的曆史指令

<code>  </code><code>118  </code><code>history</code>

<code>  </code><code>119  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>  </code><code>120  </code><code>history</code> <code>-d 199</code>

<code>  </code><code>121  </code><code>history</code> <code>-d 119</code>

<code>  </code><code>122  </code><code>history</code>  <code>|</code><code>tail</code> <code>-5</code>

<code>[root@localhost etc]</code><code># history -d 118</code>

-a: 追加目前會話的指令曆史至曆史檔案中去;

指令曆史相關的環境變量:

HISTSIZE:指令曆史中可以儲存的指令的個數;( echo $HISTSIZE,預設1000條)

HISTFILE: 指令曆史檔案;(echo $HISTFILE,使用者的曆史檔案存放的位置)

HISTFILESIZE:指令曆史檔案可以儲存的指令的個數;(echo "$HISTFILESIZE"預設1000條)

HISTCONTROL: 控制指令曆史的生成;

ignoredups: 忽略記錄重複的指令;連續的相同指令才為重複;

<code>[root@localhost ~]</code><code># echo "$HISTCONTROL"</code>

<code>ignoredups</code>

<code>[root@localhost ~]</code><code># history |tail -5</code>

<code>   </code><code>15  </code><code>echo</code> <code>"$HISTCONTRAL"</code>

<code>   </code><code>16  </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>17  </code><code>history</code>

<code>   </code><code>18  </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>19  </code><code>history</code> <code>|</code><code>tail</code> <code>-5</code>

ignorespace: 不記錄以空白字元開頭的指令;

<code>[root@localhost ~]</code><code>#  history |tail -5</code>

<code>   </code><code>31  </code><code>history</code>

<code>   </code><code>32   </code><code>echo</code> <code>"$HISTCONTROL"</code>

<code>   </code><code>33  HISTCONTROL=ignorespace</code>

<code>   </code><code>34  </code><code>ls</code> <code>/var</code>

<code>   </code><code>35  </code><code>history</code>

<code>[root@localhost ~]</code><code>#  ls /</code>

<code>bin   etc   lib64       misc  opt   sbin     sys  var</code>

<code>boot  home  lost+found  mnt   proc  selinux  tmp</code>

<code>dev   lib   media       net   root  srv      usr</code>

<code>[root@localhost ~]</code><code>#   history |tail -5</code>

ignoreboth: 同時具有上面兩種特性;

指令行編輯(快捷鍵)

ctrl+a:光标移動到行首

ctrl+e:光标移動到行尾

ctrl+u:清除光标前至行首的所有内容

ctrl+k:清除光标後至行尾的内容

ctrl+l:清屏

Ctrl+f光标向後移動一個字元

ctrl+b:光标向前移動一個字元

ctrl+h:删除光标前的一個字元

ctrl+d:從目前shell登出(和exit很像) "EOF"(檔案結束符)

ctrl+i:就是一個tab鍵

ctrl+j:新行

ctrl+m:回車

esc b:左移一個單詞

esc f:右移一個單詞

輸入、輸出重定向、管道

在linux系統中,資料流可分為3類:資料輸入,資料輸出和錯誤輸出,相對的,每一個程序也都有3個特殊的檔案描述:标準輸入(stdin,檔案描述指針為0),标準輸出(stdout,檔案描述指針為1)和标準錯誤輸出(stderr,檔案描述指針為2),這3個特殊檔案描述指針使程序在通常情況下接收标準輸入裝置的輸入,由标準輸出裝置顯示輸出.

而在輸入通常指傳給一個指令的鍵盤輸入。通常标準輸出是被定向到顯示器,如果在執行過程中發生錯誤,可能會發生錯誤,可能會存在一條錯誤消息,這是标準錯誤資料流,通常也會被定向到顯示器。有兩種基本的方法可以用來重定向标準輸入(stdin)、标準輸出和标準錯誤(stderr),可以利用管道把這些資料流之一輸送組另一個指令,也可以利用I/O重定向把這些資料流之一重定向一個檔案.所謂管道是指将某一個指令的輸出結果傳送到另一個指令,當成另一外指令的輸入,其代表符号是"|".所謂I/O重定向是指指令執行的結果重新導出到其他裝置或檔案(以"&gt;"或“&gt;&gt;”來表示)或是重新導入到其他裝置或檔案(以"&lt;"或"&lt;&lt;"來表示)

分類:

輸入重定向:&lt;, &lt;&lt;

&lt;: 輸入重定向

&lt;&lt; EOF: 此處建立檔案, Here Document

常用于在腳本中建立檔案或生成菜單;

<code>[root@localhost script]</code><code># cat  echo.sh</code>

<code>cat</code> <code>&lt;&lt;EOF</code>

<code>   </code><code>cpu) print cpu  information</code>

<code>   </code><code>mem) print memory information</code>

<code>   </code><code>disk) print disk information</code>

<code>   </code><code>quit) quit</code>

<code>EOF</code>

<code>[root@localhost script]</code><code># bash echo.sh</code>

輸出重定向:&gt;, &gt;&gt;

&gt;: 覆寫輸出

<a href="http://s3.51cto.com/wyfs02/M02/18/D8/wKioL1MTKB2grzYZAAJzU8gwCcM024.jpg" target="_blank"></a>

&gt;&gt;: 追加輸出

set -C:禁止使用覆寫重定向至已經存在的檔案;

set +C: 關閉上述特性;

&gt;|:在-C特性下,強制使用覆寫重定向;

錯誤重定向:2&gt;, 2&gt;&gt;

2&gt;: 覆寫

将錯誤的資訊輸出到指定的文本中(會覆寫原文本的内容)

2&gt;&gt;: 追加

将錯誤輸出到文本的的最後一行(不會覆寫原文本的内容)

<a href="http://s3.51cto.com/wyfs02/M01/18/DC/wKiom1MTLDaBqUP6AACK5BSVcm8103.jpg" target="_blank"></a>

<a href="http://s3.51cto.com/wyfs02/M00/18/DC/wKiom1MTLEqjhq_NAAEB6Rvp_8Q477.jpg" target="_blank"></a>

管道

在linux系統中,管道的主要功能是将其他程式的輸出結果直接導出到另一個程式作為輸入資料,即将前一個程式的輸出作為後一個程式的輸入

<a href="http://s3.51cto.com/wyfs02/M01/18/DF/wKioL1MTLlCDj6N7AABNoievvO0837.jpg" target="_blank"></a>

并不是所有的指令都可以用管道接收

<code>#pwd</code>

<code>/var/log</code>

<code>#ls /var/log | file</code>

此指令将無法執行。(由于file在此時引用的是相對路徑,如果想正确使用必須要使用如下方法)                

<code>#file `ls /var/log`|cut -d: -f2 |tr -d ' '|sort|uniq</code>

(檢視var/log下的檔案類型,并取出第二段,除去前端的空格,排序,并去掉重複的.)

tee:

将第一個指令的結果儲存到檔案并同時輸出到顯示器。

<code>#ls /etc |tee /tmp/etc.out |tr 'a-z' 'A-Z'|tr -d '0-9'</code>

此指令就是将/etc下的所有目錄或檔案,全輸出到/tmp/etc.out并在顯示器顯示時,去掉'0-9'的數字(/tmp/etc.out中的資料并不會是以而發生變化。)

指令别名

alias, 假名,别名,bash的一個内建指令,用來給常用的較長的指令定義個簡短的名稱。

alias指令的基本格式為alias [word[='command']], []内為可選項。定義word為command的别名。若=’command’部分省略,則輸出word之前的定義,未定義則報錯。單獨的alias列出目前環境中所有可用的别名。通常來講,關于alias,知道這麼多就行了。但在使用alias的過程中還有一些問題需要注意。

如果bash的expand_aliases選項沒有被設定,那麼在非互動式shell中alias不會被執行展開。也就是說,在shell腳本中,使用alias會導緻”command not found”的錯誤。使用shopt指令來設定expand_aliases選項:

<code>#設定别名擴充(啟用别名)</code>

<code>#shopt -s expand_aliases</code>

=======================================第一部份========================================

本文轉自 jinlinger 51CTO部落格,原文連結:http://blog.51cto.com/essun/1365977,如需轉載請自行聯系原作者