linux-shell詳解

Shell綜述

簡單的說:shell是用戶和Linux操作系統之間接口,提供了與操作系統之間通訊的方式。        
shell基本上是一個命令解釋器,它接收用戶命令(如ls等),然後調用相應的應用程序。        
主要學習/bin/bash它兼容於sh,一句使用者需求,而加強的sh版本。        
shell中的變量:變量的概念源於數學,在計算機中能存儲計算結果,活表示值。例如:y=5x+8其中y就是變量。環境變量對bash的影響:        
PATH:能不能執行某命令和PATH有關,如果在PATH中找不到相關命令,屏幕會出現command not found        
普通用戶PATH例子:        
PATH=/sbin:/usr/java/jdk1.8.0_45-cloudera/bin:/usr/local/apache-ant/apache-ant-1.9.2/bin:/usr/local/apache-maven等        
舉例:讀取登陸用戶名:echo $LOGINAME,讀取用戶home目錄:echo $HOME,讀取當前系統默認shell:echo $SHELL        
讀取變量另一種格式:echo ${LOGNAME}        
環境變量:使用env觀察環境變量---  env|more        
Linux是一個多用戶多任務的操作系統,所以在Linux中不同用戶具有不同的運行環境,在這樣的不同環節中,可以爲不同的用戶指定不同的環境變量        
舉例:使用set或env觀察環境變量
普通變量->環境變量:1、export 變量名=值,2、變量名1=值1,變量名2=值2,export 變量名1 變量名2        
export var=teduhadoop -> env|grep var MAIL=/var/spool/mail/root  var=teduhadoop

1)變量和值之間以一個等號"="連接(name=value)    
2)變量、值和等號之間不能有空格    
3)變量名稱只能是英文字母、數字、下劃線、但開頭不能是數字。    
4)變量內容若有空格符可使用雙引號或者單引號將變量內容結合起來。(''單引號使特殊字符不生效,""雙引號生效)    
5)變量內容由其他命令提供,使用$(其它命令)    
例:version=$(uname):把變量version設定值爲命令uname    
echo $version:和執行uname效果一樣,把系統版本打印出爲Linux    
version=$(uname -a),echo $version 之後,則顯示出Linux系統的全部內容    
version=$(uname),version=$version-$(uname-p),echo $version    
6)通常變量名大寫爲系統默認變量,自己定義變量可以使用小寫,方便區分。    
7)取消變量的定義:unset 變量名(如果取消系統環境變量的話,修改/etc/profile文件,否則重啓後該變量還中存在)    
命令定義爲變量使用案例:    
fname=$(uname-n)_$(date+%F)->echo $fname-> localhost.localdomain_2016-11-03    
tar -zcf etc_${fname}.tar.gz /etc    
8)變量總結:①全局變量:一般全大寫,如環境變量②:局部變量:腳本函數中的局部變量通常使用local    
③把一個命令定義成一個變量④${WEEK}day若變量和其他字符組成新的變量就必須給變量加上大括號,否則容易出錯    
9)數據重定向:    
數據重定向就是將某個命令執行後應該要出現在屏幕上的數據,給他傳輸到其他的地方,例如傳輸到文件或是其它命令。通常執行一條命令的時候會有標準輸出和標準錯誤輸出,標準輸出是指命令執行之後,傳回正確信息的輸出目標,標準錯誤輸出是命令執行失敗後,所傳回錯誤信息的輸出目標。    
數據重定向編號:    
標準輸入(stdin):編號爲0    
標準輸出(stdout):編號爲1    
標準錯誤輸出(stderr):編號爲2    
1>:以覆蓋的方法,將正確的數據輸出到文件;    
1>>:以累加的方法,將正確的數據輸出到文件;    
2>:以覆蓋的方法,將錯誤輸出的數據輸出到文件;
2>>:以累加的方法,將錯誤輸出的數據輸出到文件;    
舉例:將ls的輸出重定向到ls.log當中    
# ll 1>ls.log->cat ls.log

10)命令執行判斷:            
$?:命令回傳值,&&:若cmd1執行完畢且正確執行($?=0),則開始執行cmd2,若cmd1執行完畢且錯誤            
($?≠0),則cmd2不執行。            
||:若cmd1執行完畢且正確執行($?=0),則cmd2不執行。若cmd1執行完畢且未錯誤($?≠0),則開始執行cmd2            
舉例:如果/tmp/test存在,則創建/tmp/test/jinxf            
ls /tmp/test && touch /tmp/test/jinxf:如果查詢/tmp/test存在,則執行touch這個創建文件的命令            
11)管道命令:            
利用Linux所提供的管道符"|"將兩個命令隔開,管道符左邊命令的輸出就會作爲管道符右邊命令的輸入。            
連續使用管道意味着第一個命令的輸出會作爲,第二個夢裏的輸入,第二個命令的輸出又會作爲第三個命令            
的輸入,以此類推。            
舉例:將ls的查詢信息傳遞給grep命令進行搜索含"Music"。ls -a|grep Music            
12)find命令(查找,搜索)            
Linux最有用的命令之一,在一個目錄(及子目錄)中搜索文件,可以指定一些匹配條件,如:按文件名,            
文件類型,用戶甚至是時間戳查找文件。            
命令格式:find [path..] [-option]            
path:find命令所查找的目錄路徑,例如用.來表示當前目錄,用/來表示系統跟目錄。            
options:find命令常用選項:            
print:將匹配的文件輸出到標準輸出。            
size:匹配文件大小。find./ -size 0; 顯示文件大小爲0的文件            
name:按照文件名查找文件。find / -name demo 在/目錄及子目錄下面查找名字爲demo的文件。            
find . -name "*.java" 在當前目錄及其子目錄(用"."表示中查找任何擴展名爲"java"的文件)            
perm按照權限來查找文件:find . -perm 755 [-print] 在當前目錄下查找文件權限爲755的文件,            
即文件所有者讀,寫,執行,組與其他用戶可以讀,執行的文件。            
user按照文件所有者來查找文件,find ~ -user root [-print]在$HOME目錄中查找文件屬性爲root            
的文件。            
group按照文件所屬的組來查找文件。            
find / -group root [-print]在目錄下查找屬於root的用戶組文件。            
mtime -n +n :按照文件的更改時間來查找文件,-n表示文件更改時間距現在n天內,+n表示文件更改時間            
距現在n天前。            
find / -mtime -5 print 在系統跟目錄下查找更改時間在5日以內的文件。            
find / -mtime +3 -print 在/目錄下查找更改時間在3日以前的文件。            
nogroup:查找無有效所屬組的文件,即該文件所屬組/etc/groups中不存在。            
find / -nogroup -print            
type作爲find命令常用選項存在,type查找某一類型文件:            
b--塊設備文件。d--目錄。c--字符設備文件。p--管道文件。l--符號連接文件。f--普通文件            
find /etc -type d -print 在/etc目錄下查找所有的目錄。            
find . ! -type d -print 在當前目錄下查找除目錄意外的所有類型文件。            
find /etc -type l -print 在/etc目錄下查找所有的符號鏈接文件。            
size n:[c]查找文件長度爲n的文件,帶有c時表示文件長度以字節計。            
find . -size +1000c -print在當前目錄下查找文件長度大於1000字節的文件。            
sed命令:非交互式文本處理工具,默認情況下,所有的輸出行都打印到屏幕上,sed編程器逐行處理            
文件(或輸入),並將結果結果發送到屏幕。具體過程如下:            
sed把當前正在處理的行保存在一個臨時緩存區中,(也成文模式空間)然後處理臨時緩衝區的行,完成後            
把該行發到屏幕上,sed每處理完一行就將其從臨時緩衝區刪除,然後將下一行讀入再處理顯示。處理完            
文件最後一行,sed便結束運行。sed把每一行都存在臨時緩衝區中,對這個副本進行編輯,所以不會修改            
源文件。sed命令格式:sed [option] "[action]" [filename]            
option:h或-help 顯示幫助。n僅顯示script處理後的結果,V或-version顯示版本信息。            
e:允許輸入數據應用多條sed命令進行編輯。f直接將sed的動作寫在一個文件內。-f filename則可以運行            
filename內的sed動作。            
13)grep命令:grep(global search regular expression(RE) and print out the line,全面搜索正則表達式並把行打印出來)            
一種強大的文件搜索工具,它能使用正則表達式搜索文本,並把匹配的行打印出來。            
grep命令的一般形式,grep [OPTIONS] PATTERN [FILE...],-?:同時顯示匹配行上行下的?行。            
如:grep -2 pattern filename同時顯示匹配行的上下2行。            
14)tail:(跟蹤,監視)把某個檔案文件的最後幾行顯示到終端上,如果該檔案有更新,tail會自動刷新,確保你看到最新的            
檔案內容。tail [-F] [-c Number | -n Number | -m Number | -b Number | -k Number] [File]            
-F該參數用戶見識File文件增長。-c Number 從Number字節位置讀取指定文件。            
-n Number從Number行位置讀取指定文件。-m Number從Number多字節字符位置讀取指定文件,比如你的文件            
如果包含中文字,如果指定-c參數,可能導致截斷,但是使用-m會避免該問題。            
例子:tail -F filename 顯示filename文件的尾部內容(默認10行,相當於添加參數,-n 10 )            
刷新顯示在屏幕上,退出ctrl+c            
tail -n 20 filename 顯示filename最後20行            
15)sort:sort命令默認的情況下是按照字符排序。-n:按照數值排序,-u不出現重複的行。-t指定分段的符號            
-k之地你給的第幾個段,-r逆向排序            
例子:原始文件demo,cat demo :192.168.1.1  192.168.1.3  192.168.1.5  192.168.1.4            
對文件進行排序: sort demo ---> 192.168.1.1  192.168.1.3  192.168.1.4  192.168.1.5            
對文件逆序排序:sort -r demo > d1 ->192.168.1.5  192.168.1.4  192.168.1.3  192.168.1.1            
對文件進行制定分隔符,並對第四個字段排序:sort -t "." -k 4 demo(以.爲分割,第四段就是例子中的最後一段數字)            
16)cut:在文件中負責剪切數據,命令格式:cut [-option] filename            
option:-b字節,-c字符,-f提取第幾列,-d按指定分隔符分割列。            
例:每一行第五到第七字節:cut -b 5-7 st >demo            
以點爲分隔符,獲取第二個字段:cut -d . -f 2 demo            
17)history命令:顯示全部歷史,history 5 顯示執行過的上5條命令,history !!運行上一條命令history !88運行第88條命令

Shell腳本編寫

shell script其實就是純文本文件,以固定的語法組織起來,可以編輯這個文件,讓這個文件幫助我們一次執行多個命令。可以通過一些運算與邏輯判斷來幫我們達成某些複雜的功能。shell命令執行是從上而下,從左而右執行;命令,選項與參數間的多個空格會被忽略空白行也被忽略調,tab被視爲空格;如果讀取一個Enter符號(CR),就嘗試開始執行該行命令            
#後面內容爲註釋。            
shell的執行:            
程序文件名是:/home/shell.sh,執行腳本有三種方式:            
①直接執行(shell.sh文件必須具備可讀與可執行(rx)的權限):            
絕對路徑:運行/home/shell.sh來執行指令,相對路徑:cd到/home/,使用./shell.sh執行。            
②source 執行: source shell.sh            
③bash執行:bash shell.sh            sh shell.sh            
shell腳本案例:第一行#!/bin/bash,告訴系統如何執行腳本。當採用直接執行(不是用類似sh xxx.sh)時            
#!/bin/bash            此行必須有,且要放在首行。
#Shows system date            除了第一行的之外#都是註釋,其他爲程序部分。
echo $(date + %F)            exit 0,以0作爲該腳本的執行返回值。執行正常退出返回0,一個腳本執行完成
exit 0            之後的shell進程可以通過$?獲取執行結果:echo $?
shell腳本--數值運算:簡單的加減乘除,格式:$((運算內容)),兩個括號爲規定            
例:兩數相稱(交互shell腳本)            
#!/bin/bash            
# User inputs 2 integer numbers;program will cross these two             
read -p "first number: "num1   ----把信息提示出來            
read -p "second number: "num2   ----把信息提示出來            
total=$(($num1*num2))            
echo -e "\nThe result of $num1 * $sum2 is ==> $total" exit 0            
test判斷命令:使用範圍:test -e demo.txt            
-e該文件是否存在,-f該文件是否存在且爲文件,-d該文件名是否存在且爲目錄            
-b該文件是否存在且爲一個block device 裝置,-c該文件是否存在企鵝爲一個character device裝置            
-S發u胃不好事故覅有詞語不再且爲一個Socket文件,-p該文件是否村子啊且爲一個FIFO(pipe)文件            
-L該文件是否存在且爲連接文件。-nt 判斷file1是否比file2新,-ot判斷file1是否比file2舊            
-ef 判斷兩個文件是否爲同一個文件。            
判斷符號[](基本跟test相同):            
[ ]腳本返利(注意[]和腳本之間保留空格)            
==和!=用戶比較字符串;整數比較只能使用-eq,-gt這種形式            
[]中的邏輯和邏輯或使用-a和-o表示。            
&& ,||  <和>操作符如果出現按在[]結構中的話,會報錯。            
#!/bin/bash            
#this shell show user's choice            
read -p "Please input(Y/N):"yn            
["$yn" == "Y" -o "$yn" == "y"]&&echo "choice Yes"&&exit 0            
["$yn" == "N" -o "$yn" == "n"]&&echo "choice No"&&exit 0            
Shell script默認參數:            
比如,ls  -al其中-al就是shell腳本參數,那麼我們自己寫的腳本參數該如何使用?            
/path/to/scriptname         arg1    arg2    arg3    arg4            
   $0                                $1      $2      $4            
$0:代表腳本程序本身,$1,$2代表後面第一個參數,第二個參數,等等            
$# :代表後面參數個數,以上邊爲例,這裏顯示爲4            
$@:代表"$1""$2""$3""$4",每個變量是肚子裏的(用雙引號括起來)            
$*:代表"$1 $2 $3 $4"

Shell的條件判斷語句:                                        
if [ 條件判斷 ]        前後要有空格                                        
   then   換行時候用then                                        
if [ 條件判斷 ];   then                                        
條件成立執行,命令;fi 將if反過來寫,就稱爲f結束if語句                                        
&&代表 and || 代表or。                                        
例子:                                        
#!/bin/bash                                        
#compare the size of the two numbers                                        
a=12                                        
b=13                                        
if[$a -gt $b]                                        
then                                         
echo "yew $a>$b"                                        
exit 0                                        
fi                                        
if[$a -le $b];then                                        
echo "yew $a<=$b"                                        
fi                                        
多分支結構:還有一種是基於case的條件語句!!!                                        
if [ 條件1 ];then     ----條件1成立,執行指令集1                                        
elif [ 條件2 ];then        -----條件2成立,執行指令集2                                        
else  條件都不成立,執行指令集3                                        
fi                                                            
Shell的循環語句:                                        
循環可以不斷的執行某個程序段落,直到用戶設置的條件達成位置,這被稱之爲不定循環,除這之外,還有另外一種已經固定要執行多少此循環這稱之爲固定循環。                                        
不定循環:while do done,util do done                                        
固定循環:for ... do done                                        
1)while循環語句:                                        
while [ condition條件 ]  do                                        
命令                                        
done                                        
例:每隔兩面打印系統的負載情況。                例:使用while循環,編寫shell腳本,計算1+2+3+...+100的和並輸出                        
vim while1.sh                                                    vim while2.sh                        
#!/bin/bash                                                       #!/bin/bash                        
while true                                                          sum=0                        
do                                                                         i=1                        
  uptime    #系統負載情況                               while [$i -le 100] #while和[之間要加一個空格,true則執行                        
  sleep 2   #休眠2秒                                              do                        
done                                                                i=$(($i+1)) #運算結果爲變量賦值可以使用$((...))                        
ctrl+c 結束死循環。                                           sum=$(($sum+$i))                        
                                                                            done                        
                                                                        echo "the result of '1+2+3+...+100'" is $sum                        
                                        
2)until循環語句:                                      --------------------->舉例:                                        
until [ condition條件 ]; do                                             #!/bin/bash                    
命令                                                                                   i=0                    
done                                                                           until [ "$i" -gt 5 ] #大於5                    
                                                                                    do                    
                                                                                     let square=i*i                    
                                                                                   echo "$i * $i = $square"                    
                                                                                       let "i++"                    
                                                                                     done                    
3)for 循環語句:                                          --------------------->舉例:                                        
for...do...done循環                                                              for 男人 in 世界                    
語法:for 變量名 in 變量取值列表                                                 do                    
do                                                                                    if [有房]&&[有車]&&[存款]&&[會做家務]&&[帥氣]; then                    
命令                                                                                           echo "我喜歡"                    
done                                                                                                 else                    
提示:在此結構中"in 變量取值列表" 可省略,省略時                    rm -f男人;                    
相當於使用for i in "$@"                                                                       fi;                    
                                                                                                             done                    
例子2:直接列出變量表所有元素,打印5,4,3,2,1                                        
方法1:直接列出元素方法                                        
#!/bin/bash                                        
for num in 5 4 3 2 1 #=>需要空格隔開                                        
do                                        
echo $num                                        
done

[]和[[]]區別請參照:

http://www.zsythink.net/archives/2252

在bash中,$( )與``(反引號)都是用來作命令替換的。
shell中各種括號()、(())、[]、[[]]、{}的作用:
單括號():        
另開命令組——小括號中的內容會開啓一個子shell獨立運行;括號中以分號連接,最後一個命令不需要;各命令和括號無空格        
得到命令輸出——a=$(command), 等同於a=$`command`,得到命令輸出傳遞給變量a        
初始化數組——array=(a b c d)        
雙括號(()):        
省去$符號的算術運算—— for((i=0;i<5;i++)); if (($i<5)); a=5; ((a++)) 可將 $a 重定義爲6;括號內支持多個表達式用逗號分開。         
C語言規則運算——$((exp)),exp爲符合C語言規則的運算符,表達式        
跨進制運算——二進制、八進制、十六進制運算時,輸出結果全都自動轉化成了十進制。如:echo $((16#5f)) 結果爲95 (16進位轉十進制)        
單中括號[ ]:        
字符串比較——==和!=        
整數比較——不等於:-gt:大於;-lt :小於;-eq:等於;-ne        
數組索引——array[0]        
雙中括號[[]]:        
字符串比較——可以把右邊的作爲一個模式,而不僅僅是一個字符串,比如[[ hello == hell? ]],結果爲真。[[ ]] 中匹配字符串或通配符,不需要引號。        
邏輯運算符——防止腳本許多邏輯錯誤,比如,&&、||、<和> 操作符能夠正常存在於[[ ]]條件判斷結構中,但是如果出現在[ ]結構中的話,會報錯。        
比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不適用雙括號, 則爲if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。        
退出碼——bash把雙中括號中的表達式看作一個單獨的元素,並返回一個退出狀態碼。        
if ($i&lt;5)        
if [ $i -lt 5 ]        
if [ $a -ne 1 -a $a != 2 ]        
if [ $a -ne 1] &amp;&amp; [ $a != 2 ]        
if [[ $a != 1 &amp;&amp; $a != 2 ]]        
for i in $(seq 0 4);do echo $i;done        
for i in `seq 0 4`;do echo $i;done        
for ((i=0;i&lt;5;i++));do echo $i;done        
for i in {0..4};do echo $i;done

大括號{}:

創建匿名函數——不會新開進程,括號內變量餘下仍可使用。括號內的命令間用分號隔開,最後一個也必須有分號。{}的第一個命令和左括號之間必須要有一個空格。特殊替換——${var:-string},${var:+string},${var:=string},${var:?string}

特殊替換——${var:-string},${var:+string},${var:=string},${var:?string}

      ①${var:-string}和${var:=string}:若變量var爲空,則用在命令行中用string來替換${var:-string},否則變量var不爲空時,則用變量var的值來替換${var:-string};不同之處是${var:=string}常用於判斷var是否賦值,沒有的話則給var賦上一個默認值。

      ② ${var:+string}:替換規則和上面的相反,即只有當var不是空的時候才替換成string,若var爲空時則不替換或者說是替換成變量 var的值,即空值。(因爲變量var此時爲空,所以這兩種說法是等價的) 

      ③${var:?string}:替換規則爲:若變量var不爲空,則用變量var的值來替換${var:?string};若變量var爲空,則把string輸出到標準錯誤中,並從腳本中退出。我們可利用此特性來檢查是否設置了變量的值。

注意:在上面這五種替換結構中string不一定是常值的,可用另外一個變量的值或是一種命令的輸出。

模式匹配替換——${var%pattern},${var%%pattern},${var#pattern},${var##pattern}

# 是去掉左邊(在鍵盤上#在$之左邊);% 是去掉右邊(在鍵盤上%在$之右邊);#和%中的單一符號是最小匹配,兩個相同符號是最大匹配。

第一種模式:${variable%pattern}。shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable去掉右邊最短的匹配模式

 第二種模式: ${variable%%pattern},這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable中去掉右邊最長的匹配模式

第三種模式:${variable#pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern開始,如果是,把variable中去掉左邊最短的匹配模式

 第四種模式: ${variable##pattern} 這種模式時,shell在variable中查找,看它是否一給的模式pattern結尾,如果是,把variable中去掉左邊最長的匹配模式

 這四種模式中都不會改變variable的值,其中,只有在pattern中使用了*匹配符號時,%和%%,#和##纔有區別。結構中的pattern支持通配符,*表示零個或多個任意字符,?表示僅與一個任意字符匹配,[...]表示匹配中括號裏面的字符,[!...]表示不匹配中括號裏面的字符。

技巧小結
字符串比較用雙中括號[[ ]];算數比較用單中括號[ ]——左右留空格
算數運算用雙小括號(( )) ;shell命令及輸出用小括號( )——左右不留空格
快速替換用花括號{ }——左右留空格
反單引號起着命令替換的作用` `

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