Shell編程之變量的高級用法詳解

變量替換

語法 說明
${變量名#匹配規則} 從變量開頭進行規則匹配,將符合最短的數據刪除
${變量名##匹配規則} 從變量開頭進行規則匹配,將符合最長的數據刪除
${變量名%匹配規則} 從變量尾部進行規則匹配,將符合最短的數據刪除
${變量名%%匹配規則} 從變量尾部進行規則匹配,將符合最長的數據刪除
${變量名/舊字符串/新字符串} 變量內容符合就字符串,則第一個舊字符串會被新字符串替換
${變量名//舊字符串/新字符串} 變量內容符合就字符串,則全部的舊字符串會被新字符串替換

示例

var1="hello world hello world"
# 所謂最長和最短其實就是正則表達式中的貪婪模式和非貪婪模式

# 刪除匹配規則為*lo的數據(開頭最短刪除)
echo ${var1#*lo}
-> world hello world

# 刪除匹配規則為*lo的數據(開頭最長刪除)
echo ${var1##*lo}
-> world

# 刪除匹配規則為hel*的數據(尾部最短刪除)
echo ${var1%hel*}
->hello world 

# 刪除匹配規則為hel*的數據(尾部最長刪除)
echo ${var1%%hel*}
->

# 替換第一個舊字符串world為Beijing
echo ${var1/world/Beijing}
->hello Beijing hello world

# 替換第一個舊字符串world為Beijing
echo ${var1/world/Beijing}
->hello Beijing hello Beijing

變量測試

變量置換方式 變量y沒有設置 變量y為空值 變量y設置值
x=${y-新值} x=新值 x為空 x=$y
x=${y:-新值} x=新值 x新值 x=$y
x=${y+新值} x為空 x=新值 x=新值
x=${y:+新值} x為空 x為空 x=新值
x=${y=新值} x=新值 x為空 x=$y
y=新值 y值不變 y值不變
x=${y:=新值} x=新值 x=新值 x=$y
y=新值 y=新值 y值不變
x=${y?新值} 新值輸出到標準錯誤輸出(屏幕) x為空 x=$y
x=${y:?新值} 新值輸出到標準錯誤輸出 新值輸出到標準錯誤輸出 x=$y
  • 如果大括號內沒有”:”,則變量 y 為空或沒有被設置,處理方法是不同的;如果大括號內有”:”,則變量 y
  • 不論是為空,還是沒有被設置,處理方法是一樣的;
  • 如果大括號內是”-“或”+”,則在改變變量 x 的值的時候,變量 y 的值是不改變的;
  • 如果大括號內是”=”,則在改變變量 x 的值的同時,變量 y 的值也會改變;
  • 如果大括號內是”?”,則當變量 y 不存在或為空時,會把”新值”當成報錯輸出到屏幕上。

示例

# x=${y-新值}
echo ${y=$var1}
->hello world hello world

y=
echo ${y-$var1}
->

y=hello Beijing
echo ${y-$var1}
->hello Beijing

# x=${y:-新值}
echo ${y:-$var1}
->hello world hello world

y=
echo ${y:-$var1}
->hello world hello world

y=hello Beijing
echo ${y:-$var1}
->hello Beijing

# x=${y+新值}
echo ${y+$var1}
->

y=
echo ${y+$var1}
->hello world hello world

y=hello Beijing
echo ${y+var1}
->hello world hello world

# x=${y:+新值}
echo ${y:+$var1}
->

y=
echo ${y:+$var1}
->

y=hello Beijing
echo ${y:+var1}
->hello world hello world

# x=${y=新值}
x=${y=$var1}
echo $x
->hello world hello world
echo $y
->hello world hello world

y=
x=${y=$var1}
echo $x
->
echo $y
->

y=hello Beijing
x=${y=$var1}
echo $x
->hello world hello world
echo $y
->hello Beijing

# x=${y:=新值}
x=${y:=$var1}
echo $x
->hello world hello world
echo $y
->hello world hello world

y=
x=${y:=$var1}
echo $x
->hello world hello world
echo $y
->hello world hello world

y=hello Beijing
x=${y:=$var1}
echo $x
->hello Beijing
echo $y
->hello Beijing

# x=${y?新值}
echo ${y?$var1}
->-bash: y: hello world hello world

y=
echo ${y?$var1}
->

y=hello Beijing
echo ${y?$var1}
->hello Beijing

# x=${y:?新值}
echo ${y?$var1}
->-bash: y: hello world hello world

y=
echo ${y:?$var1}
->-bash: y: hello world hello world

y=hello Beijing
echo ${y:?$var1}
->hello Beijing

 看完瞭我還是記不住!!參考上表吧!

字符串處理

字符串長度

語法 說明
方法一 ${#string}
方法二 expr length “$string” string有空格,則必須加雙引號

示例

# 方法一
var1="hello world"
echo ${#var1}
->11

# 方法二
len=`expr length "$var1"`
echo $len
->11

## var1有空格,必須加雙引號,否則報錯
expr: syntax error

## var2沒有空格,可以不需要加雙引號
var2=hello
expr length $var2
5

子串字符索引

語法 expr index $string $substring string/substring有空格,則必須加雙引號 此方法並不是查找子串的索引位置,它會把子串進行字符拆分,哪個字符最先找到瞭則返回其索引位置。並且索引從1開始
expr index "$var1" llo
->3

expr index "$var1" lole
->2

子串長度

語法 expr match $string substring string/substring有空格,則必須加雙引號
expr match "$var1" hel
->3

expr match "$var1" llo
->0

expr match $string substring獲取子串長度必須是從頭開始匹配

抽取子串

語法 說明
方法一 ${string:position} 從string中的position開始抽取子串
方法二 ${string:position:length} 從string中的position開始,抽取長度為length的子串
方法三 ${string: -position} (註意-position前有個空格)從尾部開始的position抽取子串
方法四 ${string:(position)} 從string中的頭部開始的position抽取子串
方法五 expr substr $string $position $length 從string中的position開始,抽取長度為length的子串

示例

# 方法一
echo ${var1:2}
->llo world

# 方法二
echo ${var1:2:5}
->llo w

# 方法三
echo ${var1: -2}
->ld

echo ${var1: -2:1}
->l

# 方法四
echo ${var1:(3)}
->lo world

echo ${var1:(3):2}
->lo

echo ${var1:(-2):1}
->l

# 方法五
expr substr "$var1" 2 5
->ello

註意:expr substr $string $position $length的position從1開始,而${string:position:length}的從0開始。

var2=hello
echo ${var2:2:5}
->llo

expr substr $var2 2 5
->ello

小試牛刀

      需求描述:變量string=”Bigdata process framework is Hadoop,Hadoop is an open source project.”執行腳本後,打印輸出string字符串變量,並給出用戶一下選項:

  • 打印string長度
  • 刪除字符串中所有的Hadoop
  • 替換第一個Hadoop為Mapreduce
  • 替換所有Hadoop為Mapreduce

      用戶輸入數字1|2|3|4,可以執行對應項的功能;輸入q|Q則退出交互模式。

#!/bin/bash

string="Bigdata process framework is Hadoop,Hadoop is an open source project."


function print_tips
{
 echo "=============================="
 echo "1->打印string長度"
 echo "2->刪除字符串中所有的Hadoop"
 echo "3->替換第一個Hadoop為Mapreduce"
 echo "4->替換所有Hadoop為Mapreduce"
 echo "q|Q->退出"
 echo "=============================="
}

function len_of_string
{
 echo "${#string}"
}

function del_hadoop
{
 echo "${string//Hadoop/}"
}

function rep_first_hadoop_mapreduce
{
 echo "${string/Hadoop/Mapreduce}"
}

function rep_all_hadoop_mapreduce
{
 echo "${string//Hadoop/Mapreduce}"
}
while true
do
 echo ""
        echo ""
        echo ""
        echo ""
 echo "【string=$string】"
 print_tips
 read -p "Please input your choice (1|2|3|4|q|Q):" choice
 case $choice in
  1)len_of_string;;
  2)del_hadoop;;
  3)rep_first_hadoop_mapreduce;;
  4)rep_all_hadoop_mapreduce;;
  q|Q)exit;;
  *)echo "Error input,only in (1|2|3|4|q|Q)";;
 esac
done

命令替換

      Shell 命令替換是指將命令的輸出結果賦值給某個變量。比如,在某個目錄中輸入 ls 命令可查看當前目錄中所有的文件,但如何將輸出內容存入某個變量中呢?這就需要使用命令替換瞭,這也是 Shell 編程中使用非常頻繁的功能。

語法
方法一 `command`
方法二 $(command)

示例

# 獲取系統的所有用戶並輸出
#!/bin/bash

index=1
for user in `cat /etc/passwd | cut -d ":" -f 1`
do
 echo "這是第 $index 個用戶,名稱為:$user"
 index=$(($index + 1))
        # $(())主要用來進行整數運算,引用變量前面可以加$也可以不加
done

# 根據系統時間計算今年或明年
#!/bin/bash

year=`date +%Y`
echo "今年是$year年,明年是$(($year+1))年"

# 根據系統時間獲取今年還剩下多少星期,已經過瞭多少星期
#!/bin/bash

# 計算現在是今年第幾天
#!/bin/bash

days=$(date +%j)
weeks=$((days/7))
remain_weeks=$((52-weeks))
echo "今年還剩$remain_weeks個星期,已經過瞭$weeks個星期"

# 判定nginx進程是否存在,若不存在則自動拉起進程
#!/bin/bash

nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)
if [ $nginx_process_num -eq 0 ];then
 echo "nginx未啟動,拉起中..."
 systemctl start nginx
else
 echo "nginx已啟動..."
fi

有類型變量

      在之前的變量聲明中都是沒有指定變量類型的,在Shell編程中如果需要為變量指定類型則需要使用declare和typeset命令。這兩個命令是等價的。(下表中-號為添加,取消則使用+號,如+x)

參數 含義
-r 將變量設置為隻讀
-i 將變量設置為整數
-a 將變量定義為數組
-f 顯示此腳本前定義過的所有函數及內容
-F 僅顯示此腳本前定義過的函數名
-x 將變量聲明為環境變量

示例

# 設置為隻讀
var1="hello wordl"
var1="hello shell"
declare -r var1
var1="hello java"
->-bash: var1: readonly variable

# 設置為整形
num1=20
num2=$num1+30
echo $num2
->20+30 #linux默認設置為字符串
declare -i num3
num3=$num1+30
echo $num3
->50

# 定義數組
declare -a array
array=(1 2 3 4)
# 輸出全部內容
echo ${array[@]} 
# 輸出下標索引為1的內容
echo ${array[1]}
# 數組內元素個數
echo ${#array[@]}
# 指定索引賦值
array[0]=555
# 尾部添加元素
array[4]=666
# 刪除元素
# 刪除索引為2的元素
unset array[2]
# 清空整個數組
unset array
# 分片訪問
# 顯示數組下標索引從1開始到3的三個元素(包頭不包尾)
${array[@]:1:4}
# 數組遍歷
for n in ${array[@]}
do
    echo $n
done

# 顯示腳本前定義過的所有函數及內容
# 在前問小試牛刀的print_tips方法後添加declare -f,即可發現隻顯示瞭命令前的函數及內容

數學運算之expr

expr操作符對照表:

操作符 含義
num1 | num2 num1不為空且非0,返回num1;否則返回num2
num1 & num2 num1不為空且非0,返回num1;否則返回0
num1 < num2 num1小於num2,返回1;否則返回0
num1 <= num2 num1小於等於num2,返回1;否則返回0
num1 = num2 num1等於num2,返回1;否則返回0
num1 != num2 num1不等於num2,返回1;否則返回0
num1 > num2 num1大於num2,返回1;否則返回0
num1 >= num2 num1大於等於num2,返回1;否則返回0

註意:如果需要在命令行中使用這些運算需要轉義,如expr $num1 \| $num2,expr $num1 \> $num2,否則報錯。

num1=20
num2=100
expr $num1 \| $num2
expr $num1 \& $num2
expr $num1 \< $num2
expr $num1 \<= $num2
expr $num1 \> $num2
expr $num1 \>= $num2
expr $num1 = $num2
expr $num1 != $num2
expr $num1 + $num2
expr $num1 - $num2
expr $num1 \* $num2
expr $num1 / $num2
expr $num1 % $num2

數學運算之bc

      bc是bash內建的運算器,支持浮點數運算。默認情況下bc運算精確到整數,可以設置scale來保留指定位數的小數。

bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
23/5
4
scale=2
23/5
4.60

     在shell中通常通過管道來使用bc。如:echo “2.5/3.65” | bc或echo ‘scale=2; (2.777 – 1.4744)/1’ | bc。註意:後者的/1操作,如果不進行除法則無法保留指定位數的小數
      bc 除瞭 scale 來設定小數位之外,還有 ibase(輸入數據的進制) 和 obase(輸出的數據進制) 來其它進制的運算。

echo "ibase=2;111" |bc
->7

echo "obase=2;192" |bc
->11000000


到此這篇關於Shell編程之變量的高級用法詳解的文章就介紹到這瞭,更多相關Shell 變量的高級用法內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: