shell學習

Shell是用戶與Linux操作系統溝通的橋樑

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




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