Linux之shell 基本知識
一、shell環境定義
-
臨時環境變數
臨時環境變數指的是使用者在當前環境變數生效的變數,使用者登陸系統後,直接在命令列定義的環境變數只能在當前的登陸環境中使用,當退出系統後,臨時環境變數則失效
-
將環境變數永久生效
通過將環境變數定義寫入到配置檔案中,使用者每次登陸時系統自動定義,則無需再到命令列重新定義。
定義環境變數的常見配置檔案如下:
系統環境變數:/etc/profile 針對系統所有使用者生效
使用者環境變數:$HOME_name/.bash_profile 針對特定使用者生效。當用戶登陸系統後,首先繼承/etc/profile檔案中的定義,
再應用$HOME/.bash_profile檔案中的定義。
系統預定義的環境變數:如 $PATH、$HOME、$SHELL、$PWD等等,對所有使用者有效
二、shell指令碼程式設計
-
建立shell指令碼
一個shell指令碼通常包含如下部分:
首行
第一行內容在指令碼的首行左側,表示指令碼將要呼叫的shell直譯器,內容如下:
#!/bin/bash
#! 符號能夠被核心識別是一個指令碼的開始,這一行必須位於指令碼的首行,/bin/bash是bash程式的絕對路徑,
在這裡表示後續的內容將通過bash程式解釋執行
建立指令碼的三種方式:
第一種:#echo "" >first.sh 第二種: #touch first.sh 第三種: #vi firsh.sh
註釋:
帶#開頭的就是一段註釋
-
shell指令碼的許可權
一般情況下,預設建立的指令碼是沒有執行許可權的,需要自行修改許可權
修改許可權
-
shell指令碼的執行
1、輸入指令碼的絕對路徑或相對路徑
絕對路徑:/home/hyx/test.sh 相對路徑:./test.sh
2、bash或sh+指令碼
bash test.sh sh test.sh
注意:當指令碼沒有x許可權時,root和檔案所有者可以通過該方式正常執行。
3、在指令碼的路徑前再加“.”,或source
source test1.sh ./test1.sh
區別:
第一種和第二種會新開一個bash,不同bash中的變數無法共享
第三種是在同一個shell裡面執行的
-
shell變數
變數的分類
Linux Shell中的變數分為使用者自定義變數、環境變數、位置引數變數和預定義變數
可以通過set參看系統中存在的變數
-
(1)使用者自定義變數
使用者自定義變數由字母或下劃線開頭,由字母,數字或下劃線序列組成,並且大小寫字母的意義不同,變數名
長度沒有限制
設定變數:習慣上用大寫字母來命名變數。變數名以字母表示的字元開頭,不能用數字。
變數的呼叫
在使用變數時,要在變數名前加上字首"$",使用echo檢視變數值
echo $A
變數賦值
1、定義時賦值:變數=值(注意等號兩邊都不能有空格)
A="hello world"
2、將一個命令的執行結果賦值給變數
A=`ls -l` ## 反引號,執行裡面的命令,並將結果返回給變數A A=$(ls -l) ## 等價於上面
3、將一個變數賦值給另一個變數
A="hello world" B=$A
變數疊加
AA=123 BB="$AA"456 CC=${AA}789
補充:
單引號和雙引號的區別:單引號會將所有特殊字元脫意
列出所有的變數
set
刪除變數
unset AA
注意:使用者自定義的變數,作用域為當前的shell環境
-
(2)環境變數
環境變數在當前shell和其所有的子shell中生效。如果將環境變數寫入相應的配置檔案,那麼這個環境變數就會在
所有的shell中生效
export 變數名=變數值 申明變數
作用域:當前shell以及所有的子shell
-
(3)位置引數變數
-
(4)預定義變數
-
read命令
格式:read [選項] 值
read -p(提示語句) -n(字元個數) -t(等待時間,單位為秒) -s(隱藏輸入)
-
運算子
Num1=11 Num2=22 Sum=$Num1+$Num2 echo Sum
格式:expr m + n(注意運算子前後必須要有空格) 或 $((m+n))
expr 3 + 5 echo `expr 3 \* 5`(\是轉移符)
計算 (2+3)*4
## 第一種方式 S=`expr 2 + 3` expr $S \* 4 ## 第二種方式 expr `expr 2 + 3` \* 4 ## 第三種方式 echo $(((2+3)*4))
補充:$()和${}的區別
$()的用途和反引號``一樣,表示優先執行的命令
${}則是取變數
$((運算內容)) 適用於數值運算
-
條件測試
內建test命令
內建test命令常用操作符號[]表示,將表示式寫在[]裡面,如下:
[ expression ] ,(注意:表示式首尾都要留空格)
或者 test expression
測試範圍:整數、字串、檔案
表示式的結果為真,則test的返回值為0,反之為1
字串測試:
test str1 == str2 測試字串是否相等 = test str1 != str2 測試字串是否不相等 test str1 測試字串是否不為空 test -n str1 測試字串是否不為空 注意str1加雙引號和不加的區別 test -z str1 測試字串是否為空
整數測試:
test int1 -eq int2 測試整數是否相等 equals test int1 -ge int2 測試int1是否>=int2 test int1 -gt int2 測試int1是否>int2 test int1 -le int2 測試int1是否<=int2 test int1 -lt int2 測試int1是否<int2 test int1 -ne int2 測試整數是否不相等
檔案測試:
test -d file ;echo $? 指定檔案是否目錄 test –e file ;echo $? 檔案是否存在 exists test -f file ;echo $? 指定檔案是否常規檔案 test –L File ;echo $? 檔案存在並且是一個符號連結 test -r file 指定檔案是否可讀 test -w file 指定檔案是否可寫 test -x file 指定檔案是否可執行
多重條件測試:
條件1 –a 條件2 邏輯與 兩個都成立,則為真
條件1 –o 條件2 邏輯或 只要有一個為真,則為真
! 條件 邏輯非 取反
-
流程控制語句
-
if/else 命令
1、單分支if條件語句
if [ 條件判斷式 ] then 程式 fi 或者 if [ 條件判斷式 ] ; then 程式 fi
單分支條件語句需要注意幾個點
if語句使用fi結尾,和一般語言使用大括號結尾不同。
[ 條件判斷式 ] 就是使用test命令判斷,所以中括號和條件判斷式之間必須有空格
then後面跟符號條件之後執行的程式,可以放在[]之後,用“;”分割,也可以換行寫入,就不需要";"了。
2、多分支if條件語句
if [ 條件判斷式1 ] then 當條件判斷式1成立時,執行程式1 elif [ 條件判斷式2 ] then 當條件判斷式2成立時,執行程式2 ...省略更多條件 else 當所有條件都不成立時,最後執行此程式 fi
case語句
case命令是一個多分支的if/else命令,case變數的值用來匹配value1,value2,value3等等。
case 變數 in PAT1) 執行語句 ;; PAT2) 執行語句 ;; *) 預設執行語句 ;; esac
-
for 迴圈
第一種:
for N in 1 2 3 do echo $N done 或 for N in 1 2 3; do echo $N; done 或 for N in {1..3}; do echo $N; done
第二種:
for ((i = 0; i <= 5; i++)) do echo "welcome $i times" done 或 for ((i = 0; i <= 5; i++)); do echo "welcome $i times"; done
-
while迴圈
while [ expression ] do 執行語句 ... done 或者 while ((expression)) do 執行語句 ... done
-
自定義函式
函式的格式如下:
第一種:
函式名()
{
命令1…..
命令2….
return 返回值變數
}
第二種:
[ function ] funname [()] { action; [return int;] }
第三種:
function funname { action; return }
函式的呼叫: 直接函式名就可以呼叫函式
注意:
如果函式名後沒有(),在函式名和{ 之間,必須要有空格以示區分。
-
指令碼除錯
sh -x script
這將執行該指令碼並顯示所有變數的值。
在shell腳本里新增
set -x 對部分指令碼除錯
sh -n script
不執行指令碼只是檢查語法的模式,將返回所有語法錯誤。
sh –v script
執行並顯示指令碼內容
-
cut
cut命令是用來剪下文字檔案裡的資料,文字檔案可以是欄位型別或是字元型別。下面給出應用例項: /> cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin ... ... /> cut -d : -f 1,5 /etc/passwd #-d後面的冒號表示欄位之間的分隔符,-f表示取分割後的哪些欄位 root:root #這裡取出的是第一個和第五個欄位。 bin:bin daemon:daemon adm:adm ... ... /> cut -d: -f 3- /etc/passwd #從第三個欄位開始顯示,直到最後一個欄位。 0:0:root:/root:/bin/bash 1:1:bin:/bin:/sbin/nologin 2:2:daemon:/sbin:/sbin/nologin 3:4:adm:/var/adm:/sbin/nologin 4:7:lp:/var/spool/lpd:/sbin/nologin ... ... 這裡需要進一步說明的是,使用cut命令還可以剪下以字元數量為標量的部分字元,該功能通過-c選項實現,其不能與-d選項共存。 /> cut -c 1-4 /etc/passwd #取每行的前1-4個字元。 /> cut -c-4 /etc/passwd #取每行的前4個字元。 root bin: daem adm: ... ... /> cut -c4- /etc/passwd #取每行的第4個到最後字元。 t:x:0:0:root:/root:/bin/bash :x:1:1:bin:/bin:/sbin/nologin mon:x:2:2:daemon:/sbin:/sbin/nologin :x:3:4:adm:/var/adm:/sbin/nologin ... ... /> cut -c1,4 /etc/passwd #取每行的第一個和第四個字元。 rt b: dm a: ... ... /> cut -c1-4,5 /etc/passwd #取每行的1-4和第5個字元。 root: bin:x daemo adm:x
-
awk和sed
sed
sed是一個很好的檔案處理工具,本身是一個管道命令,主要是以行為單位進行處理,可以將資料行進行替換、刪除、新增、選取等特定工作,下面先了解一下sed的用法
sed命令列格式為:
sed [-nefri] ‘command’ 輸入文字
常用選項:
- -n:使用安靜模式。在一般sed用法中,所有的資料一般都會被列出到螢幕上,如果加上-n引數後,只有經過sed特殊處理的那一行才會被列出來。
- -e:值接在指令行模式上進行sed的工作編輯。
- -f:-f filename 可以執行filename內的sed動作。
- -r:支援擴充套件表示式
- -i:直接修改讀取的檔案內容。
常用命令:
- a:新增
- c:取代,後面可以接字串
- d:刪除
- i:插入
- p:列印,通常與sed -n一起
- s:取代,可以搭配正規表示法
例項:
刪除某行:
sed '1d' test.txt # 刪除第一行 sed '$d' test.txt #刪除最後一行 sed '1,2d' test.txt # 刪除第一行到第二行 sed '2,$d' test.txt # 刪除第二行到最後一行
顯示某行:
sed -n '1p' test.txt # 顯示第一行 sed -n '$p' test.txt #顯示最後一行 sed -n '1,2p' test.txt # 顯示第一行到第二行 sed -n '2,$p' test.txt # 顯示第二行到最後一行
使用模式進行查詢
sed -n '/test/p' test.txt # 查詢包括test所在的行 sed -n '/\$/p' test.txt # 查詢包括$所在的行
增加一行或多行字串
sed '1a hello' test.txt # 在第一行新增一行hello sed '1,3a hello' test.txt # 在第一行到第三行新增一行hello
代替一行或多行
sed '1c hello' test.txt # 第一行替換為hello sed '1,3c hello' test.txt # 第一行和第三行替換為hello
代替一行中的某部分
sed -in '/name=/p' test.txt | sed 's/name=//g' #將name=刪除 sed -i 's/name=/name/g' `grep -rl ./` #批量修改目錄下的檔案的欄位
刪除匹配行
sed -i '/匹配字元/d' 檔案 #刪除檔案中含有匹配字元的行
替換匹配行中的某個字串
sed -i '/匹配字串/s/需要替換的字串/替換後的字串/g' 檔案
awk
sed常用於一整行資料的處理,awk則更傾向於將一行資料分為多個欄位進行處理
選項說明:
awk -F "字串" 以某個字串為分隔符進行分割
例子:
檔案:test.txt
a=$(cat test.txt | awk -F "=" '{print$1}') #以“=”為分隔符,取每行的第一個欄位
結果:
常用的內建變數:
NR #行數
NF #列數