Linux的Shell種類衆多,這裏我們學習的是bash,也就是Bourne Again Shell,由於易用和免費,Bash在日常工作中被
廣泛使用,同時,Bash也是大多數Linux系統默認的Shell。
文件名後綴通常是.sh
#!/bin/bash
#這裏是註釋
在一般情況下,人們並不區分 Bourne Shell和Bourne Again Shell,所以,在這裏,我們可以看到#!/bin/bash,它同樣
也可以改爲#!/bin/sh。
shell單步調試:bash -x test.sh
shell語法檢查:bash -n test.sh
變量
變量不需要聲明,初始化不需要指定類型
變量命名
1:不能使用程序中的關鍵字(保留字)
2:只能使用數字,字母和下劃線,且不能以數字開頭
3:建議命令要通俗易懂
顯示變量值使用echo命令 ,加上$變量名,也可以使用${變量名}
例如:echo $JAVA_HOME 或者 echo ${JAVA_HOME}
變量分類
本地變量:
只對當前shell進程有效的,對子進程和其它shell進程無效。
定義:VAR_NAME=VALUE 不能有空格
變量引用:${VAR_NAME}
取消變量:unset VAR_NAME
環境變量:
自定義的環境變量對當前shell進程及其子shell進程有效,對其它的shell進程無效
定義:export VAR_NAME=VALUE
對所有shell進程都有效需要配置到配置文件中
vi /etc/profile
source /etc/profile
局部變量:
函數調用結束,變量就會消失 對shell腳本中某代碼片段有效
定義:local VAR_NAME=VALUE
位置變量:
$1,$2,.....${10}....
/tmp/test.sh a b
$0:腳本自身路徑全名
$1:腳本的第一個參數
$2:腳本的第二個參數
特殊變量:
$?:接收上一條命令的返回狀態碼 如果執行成功,返回的狀態碼是0,執行失敗的狀態碼在1-255之間 echo $?
$#:參數個數,可用於在腳本中用$#獲取傳入參數個數
$*:或者$@:所有的參數 ,可用於在腳本中用$*或$@獲取傳入的所有參數
$$:獲取當前shell腳本的進程號,可以在腳本中使用$$獲取當前腳本進程號
單引號、雙引號、反引號
''單引號不解析變量
""雙引號會解析變量
``反引號是執行並引用一個命令的執行結果,類似於$(...)
for循環
通過使用一個變量去遍歷給定列表中的每個元素,在每次變量賦值時執行一次循環體,直至賦值完成所有元素退出循環
格式1
for ((i=0;i<10;i++))
do
...
done
格式2
for i in 0 1 2 3 4 5 6 7 8 9
do
...
done
格式三
for i in {0..9}
do
...
done
條件測試
bash條件測試
命令執行成功與否即爲條件測試
test EXPR
[ EXPR ]:注意中括號和表達式之間的空格
整型測試:
-gt:大於:例如[ $num1 -gt $num2 ]
-lt:小於
-ge:大於等於
-le:小於等於
-eq:等於
-nq:不等於
字符串測試:
>:大於[ "$str1" \> "$str2" ]
<:小於
=
!=
算術運算
let varNamer=算術表達式
varName=$[算術表達式]
varName=$((算術表達式))
varName=`expr $num1 + $num2`
while/until循環
適用於循環次數未知,或不便用for直接生成較大的列表時
格式:
while 測試條件
do
循環體
done
如果測試條件爲“真”,則進入循環,退出條件爲,測試條件爲假。
until循環的格式和while循環的格式一致,但是和while循環的意思相反,如果測試條件爲假,則進入循環,退出條件爲,測試條件爲真
if判斷
單分支
if 測試條件;then
選擇分支
fi
雙分支
if 測試條件
then
選擇分支1
else
選擇分支2
fi
多分支
if 條件1; then
分支1
elif 條件2; then
分支2
elif 條件3; then
分支3
...
else
分支n
fi
例子:
if [ $1 -eq 1 ]
then
echo "one"
elif [ $1 -eq 2 ]
then
echo "two"
else
echo "none"
fi
case判斷
有多個測試條件時,case語句會使得語法結構更清晰
格式: case 變量引用 in
PATTERN1)
分支1
;;
PATTERN2)
分支2
;;
...
*)
分支n
;;
esac
PATTERN :類同於文件名通配機制,但支持使用|表示或者
a|b:a或者b
*:匹配任意長度的任意字符
?:匹配任意單個字符
[]:指定範圍內的任意單個字符
例子:
#!/bin/bash
case $1 in
1)
echo "one"
;;
2)
echo "two"
;;
3)
echo "three"
;;
*)
echo "none"
;;
esac
自定義函數
function 函數名(){
....
}
引用自定義函數文件時,使用source func.sh有利於代碼的重用性
定義fun1.sh
#!/bin/bash
function test(){
echo "hello world"
}
定義fun2.sh直接調用test()函數
#!/bin/bash
source /usr/local/fun1.sh
test
date
顯示當前時間
格式化輸出
date "+%Y-%m-%d %H:%M:%S"
格式%s表示自1970-01-01 00:00:00以來的秒數
date +%s
指定時間輸出
date --date='2009-01-01 11:11:11'
指定時間輸出
date --date='3 days ago'
獲取指定日期自1970-01-01 00:00:00以來的秒數
date --date='2009-01-01 11:11:11' +%s
read
read命令接收標準輸入(鍵盤)的輸入,或者其他文件描述符的輸入。得到輸入後,read命令將數據放入一個標準變
量中。
格式
read VAR_NAME
read -p "Enter your name:" VAR_NAME 有提示信息Enter your name:
read如果後面不指定變量,那麼read命令會將接收到的數據放置在環境變量REPLY中
read -t 5 -p "enter your name:" VAR_NAME 倒計時5秒鐘
read -s -p "Enter your password: " pass 祕密的輸入,看不到輸入的內容
declare
用來限定變量的屬性
-r 只讀
#!/bin/bash
num=0
echo $num 輸出0
declare -r num
num=1
echo $num 輸出0
-i 整數:某些算術計算允許在被聲明爲整數的變量中完成,而不需要特別使用expr或let來完成。
#!/bin/bash
declare -i num
let num=1+1
echo $num
-a 數組
字符串操作
獲取長度:${#VAR_NAME}
name=zhangsan
echo ${#name} 輸出8
字符串切片
name=zhangsan
${string:offset:length}
echo ${name:2:3} 輸出ang
取尾部的指定個數的字符
name=zhangsan
${string: -length}:注意冒號後面有空格
echo ${name: -3} 輸出san
取子串:基於模式
${variable#*word} 從左往右取第一個word後面的字符串
name=zhangsan
echo ${name#*a} 輸出ngsan
${variable##*word} 從左往右截取第二個word後面的字符串
name=zhangsan
echo ${name##*a} 輸出n
${variable%word*} 從右往左取第一個word後面的字符串
name=zhangsan
echo ${name%a*} 輸出zhangs${variable%%word*} 從右往左取第二個word後面的字符串
name=zhangsan
echo ${name%%a*} 輸出zh查找替換:
${variable/pattern/substr}替換第一次出現
${variable//pattern/substr}替換所有的出現
${variable/#pattern/substr}替換行首的pattern,如果行首沒有此字符串,則不替換
${variable/%pattern/substr}替換行尾的pattern,如果行尾沒有此字符串,則不替換
查找刪除
${variable/pattern}刪除第一次匹配的字串
${variable//pattern}刪除所有匹配的字串
${variable/#pattern}刪除行首匹配的字串
${variable/%pattern}刪除行尾匹配的字串
大小寫轉換
小-->大:${variable^^}
大-->小:${variable,,}
變量賦值操作
${parameter:-word}
如果變量parameter的值爲空或者不存在,返回結果爲word,此時變量parameter的值依然爲空
${parameter:=word}
如果變量parameter的值爲空或者不存在,返回結果爲word,此時將word賦值給變量parameter
${parameter:?word}
如果變量parameter的值爲空或者不存在,則把word當作錯誤信息返回。
${parameter:+word}
如果變量parameter的值存在,返回結果爲word。如果變量不存在,則返回爲空。
數組
定義:declare -a:表示定義普通數組
特點
支持稀疏格式
僅支持一維數組
數組賦值方式
一次對一個元素賦值a[0]=$RANDOM
一次對全部元素賦值a=(a b c d)
按索引進行賦值a=([0]=a [3]=b [1]=c)
命令替換 logs=($(ls /var/log/*.log)) 將/var/log/下所有的.log文件名作爲數組元素存儲在logs數組中
使用read命令read -a ARRAY_NAME
獲取數組的長度
${#ARRAY[*]}
${#ARRAY[@]}
注意:${#ARRAY}表示獲取數組中的第一個元素的長度,等於${#ARRAY[0]},等於$ARRAY
從數組中獲取某一片段之內的元素
格式: ${ARRAY[@]:offset:number}
offset:偏移的元素個數
number:取出的元素的個數
${ARRAY[@]:offset}:取出偏移量後的所有元素
${ARRAY[@]}:取出數組中的所有元素
數組複製:(建議使用${ARRAY[@]})
$@:每個參數都是一個獨立的串
$*:所有參數是一個串
刪除元素:
unset ARRAY[index]
腳本後臺運行,執行
sleep.sh & 但是如果關閉終端就會退出。因爲終端關閉時終端會發送hangup命令停止該終端的所有進程
可以使用:nohup sleep.sh & 這樣即使關閉終端腳本仍然繼續執行着,輸出日誌可查看當前路徑的nohup.out
標準輸入、輸出、錯誤
標準輸入、輸出、錯誤都是命令行,使用文件描述符0、1、2引用
cat > catfile < ~/.bashrc
ls >file 或者 ls 1>file 這樣把每次的輸出都會覆蓋進file,如果想追加在原內容後面可以使用ls >> file
lk 2>file(lk是一個錯誤命令)
使用重定向可以把信息轉換到其他位置
ls folder 2> /dev/null 將錯誤信息扔進黑洞
ls folder 1>/dev/null 2>&1 將正確信息和錯誤信息全扔掉
crontab定時器
使用crontab -e 添加定時任務
* * * * * echo 'date' >> /usr/local/date.log
每分鐘輸出時間信息,裏面指定的文件或腳本必須是全路徑
* * * * * echo 'date' >> /usr/local/shell.sh
每分鐘執行shell.sh腳本,必須是全路徑
可以使用tail -f /usr/local/date.log監控輸出結果
crontab定時任務可以執行的前提是必須啓動cron服務:service crond start。查看狀態:service crowd status
ps用來顯示當前shell啓動的進程相關信息
ps -e 顯示系統中所有進程
ps -ef | grep bash
jps顯示所有java進程,但是有時候查看不到,可以使用ps -ef|grep java查看在編寫批量執行腳本,需要ssh到遠程服務器執行的腳本時,由於ssh到遠程服務器時,不會主動加載/etc/profile只會
加載~/.bashrc或/tmp/bashrc,所以需要將source /etc/profile命令添加到bashrc腳本中,批量腳本才能正確加載到遠
程服務器的環境變量,腳本才能正確執行。
vi小技巧
非編輯模式下:
查找字符串:/string 找到後按n找下一個
按:輸入數字,跳到指定行
複製一行:光標移到該行任意位置,按兩下yy,複製完畢。再按p粘貼。要複製兩行先按2,光標移到第一行按yy。
跳到最後一行:大寫g