Linux bash編程基礎語法總結

前言

在Linux學習過程中,我們無可避免的會碰到一個既讓人喜歡,又令人頭疼的神奇的東西——bash編程,即shell腳本。那么什么是shell腳本呢?shell是一個命令語言解釋器,而shell腳本則是Linux命令的集合,按照預設的順序依次解釋執行,來完成特定的、較復雜的系統管理任務,類似于Windows中的批處理文件。本文帶來的是bash編程的基礎語法講解。

bash編程之變量

bash變量類別

本地變量:只對當前shell進程有效的變量,對其它shell進程無效,包當前shell進程的子進程

VAR_NAME=VALUE

變量賦值:向變量的存儲空間保存數據

變量引用:${VAR_NAME}         

"":弱引用,里面的變量會被替換
'':強引用,里面的所有字符都是字面量,直接輸出

環境變量:對當前shell進程及其子shell有效,對其它的shell進程無效         

定義:export VAR_NAME=VALUE
導出:export VAR_NAME
撤消變量:unset VAR_NAME
只讀變量:readonly VAR_NAME

局部變量:對shell腳本中某代碼片斷有效,通常用于函數本地

local VAR_NAME=VALUE

位置變量:用來接受變量指定位置的參數

$1,$2...,${10}

特殊變量:shell對一些參數做特殊處理,這些參數只能被引用而不能被賦值

$#  傳遞到腳本的參數個數
$*  顯示所有向腳本傳遞的參數                  #與位置變量不同,此選項參數可超過9個
$$  獲取當前shell的進程號
$!  執行上一個指令的進程號
$?  獲取執行的上一個指令的返回值              #0為執行成功,非零為執行失敗
$-  顯示shell使用的當前選項,與set命令功能相同
$@  與$*相同,但是使用時加引號,并在引號中返回每個參數

查看變量:

set:查看當前shell進程中的所有變量
export, printenv, env:查看當前shell進程中的所有環境變量

變量命名:

1、不能使用程序中的關鍵字(保留字)

2、只能使用數字、字母和下劃線,且不能以數字開頭

3、要見名知義

變量類型:

數值型:精確數值(整數),近似數值(浮點型)

字符型:char,string

布爾型:true, false

類型轉換:顯式轉換,隱式轉換

bash的配置文件:

profile類:為交互式登錄的用戶提供配置

全局:/etc/profile、/etc/profile.d/*.sh

用戶:~/.bash_profile

bashrc類:為非交互式的用戶提供配置

全局:/etc/bashrc

用戶:~/.bashrc

功能:設定本地變量,定義命令別名

bash編程之編寫格式及執行方式

編寫格式:

shell腳本第一行必須頂格寫,用shebang定義指定的解釋器來解釋該腳本。

#!/bin/bash       #!即為shebang

其它的以#開頭的行均為注釋,會被解釋器忽略,可用來注釋腳本用途及版本,方便使用管理。

執行方式:

bash編程屬于面向過程編程,執行方式如下:

順序執行:按命令先后順尋依次執行

選擇執行:測試條件,可能會多個測試條件,某條件滿足時,則執行對應的分支

循環執行:將同一段代碼反復執行多次,因此,循環必須有退出條件;否則,則陷入死循環

bash執行選項:

bash -n SHELLNAME  #語法測試,測試是否存在語法錯誤
bash -x SHELLNAME  #模擬單步執行,顯示每一步執行過程

bash之算數運算與邏輯運算

算數運算

定義整型變量:

let VAR_NAME=INTEGER_VALUE            #例如:let a=3
declare -i VAR_NAME=INTEGER_VALUE     #declare -i a=3

實現算術運算的方式:

let VAR_NAME=ARITHMATIC_EXPRESSION
VAR_NAME=$[ARITHMATIC_EXRESSION]
VAR_NAME=$((EXPRESSION))
VAR_NAME=$(expr $num1 + $num2)

算術運算符:

+:加法
-:減法
*:乘法
/:整除
%:取余數
**:乘冪

注意:即使沒有定義為整型變量,字符型的數字依然可以參與算術運算,bash會執行變量類型的隱式類型轉換。

邏輯運算

布爾運算:真,假
與運算:真 && 真 = 真
        真 && 假 = 假
        假 && 真 = 假
        假 && 假 = 假
或運算:真 || 真 = 真
	真 || 假 = 真
	假 || 真 = 真
	假 || 假 = 假
非運算:!真=假
        !假=真

bash編程之條件測試語句

bash條件測試

整型測試:整數比較

例如 [ $num1 -gt $num2 ]

-gt: 大于則為真
-lt: 小于則為真
-ge: 大于等于則為真
-le: 小于等于則為真
-eq: 等于則為真
-ne: 不等于則為真

字符測試:字符串比較

雙目:

例如[[ "$str1" > "$str2" ]]

>: 大于則為真
<: 小于則為真
>=:大于等于則為真
<=:小于等于則為真
==:等于則為真
!=:不等于則為真

單目:

-n String: 是否不空,不空則為真,空則為假
-z String: 是否為空,空則為真,不空則假

文件測試:判斷文件的存在性及屬性等

-a FILE:存在則為真;否則則為假;
-e FILE: 存在則為真;否則則為假;
-f FILE: 存在并且為普通文件,則為真;否則為假;
-d FILE: 存在并且為目錄文件,則為真;否則為假;
-L/-h FILE: 存在并且為符號鏈接文件,則為真;否則為假;
-b: 存在并且為塊設備,則為真;否則為假;
-c: 存在并且為字符設備,則為真;否則為假
-S: 存在并且為套接字文件,則為真;否則為假
-p: 存在并且為命名管道,則為真;否則為假
-s FILE: 存在并且為非空文件則為值,否則為假;
-r FILE:文件可讀為真,否則為假
-w FILE:文件可寫為真,否則為假
-x FILE:文件可執行為真,否則為假
file1 -nt file2: file1的mtime新于file2則為真,否則為假;
file1 -ot file2:file1的mtime舊于file2則為真,否則為假;

組合條件測試:在多個條件間實現邏輯運算

與:[ condition1 -a condition2 ]
	condition1 && condition2
或:[ condition1 -o condition2 ]
	condition1 || condition2
非:[ -not condition ]
	! condition
與:COMMAND1 && COMMAND2
COMMAND1如果為假,則COMMAND2不執行
或:COMMAND1 || COMMAND2
COMMAND1如果為真,則COMMAND2不執行
非:! COMMAND

條件測試之if語句

if語句之單分支

語句結構:

if 測試條件;then
   選擇分支
fi

表示條件測試狀態返回值為值,則執行選擇分支

例:寫一個腳本,接受一個參數,這個參數是用戶名;如果此用戶不存在,則創建該用戶;

#!/bin/bash
if ! id $1 &> /dev/null;then
	useradd $1
fi

if語句之雙分支

語句結構:

if 測試條件;then
   選擇分支1
else
   選擇分支2
fi

兩個分支僅執行其中之一

例:通過命令行給定一個文件路徑,而后判斷:如果此文件中存在空白行,則顯示其空白行的總數;否則,則顯示無空白行;

#!/bin/bash
if grep "^[[:space]]*$" $1 &> /dev/null; then
	echo "$1 has $(grep "^[[:space]]*$" $1 | wc -l) blank lines."
else
	echo "No blank lines"
fi

注意:如果把命令執行成功與否當作條件,則if語句后必須只跟命令本身,而不能引用。

補充:bash交互式編程

read [option] “prompt”

-p:直接指定一個變量接受參數
-t timaout:指定等待接受參數的時間
-n:表示不換行

例:輸入用戶名,可返回其shell

#!/bin/bash
read -p "Plz input a username: " userName
if id $userName &> /dev/null; then
    echo "The shell of $userName is `grep "^$userName\>" /etc/passwd | cut -d: -f7`."
else
    echo "No such user. stupid."
fi

if語句之多分支

語句結構:

if 條件1;then
     分支1
elif 條件2;then
     分支2
elif 條件3;then
     分支3
      ...
else
     分支n
fi

例:傳遞一個用戶名給腳本:如果此用戶的id號為0,則顯示說這是管理員;如果此用戶的id號大于等于500,則顯示說這是普通用戶;否則,則說這是系統用戶。

#!/bin/bash
if [ $# -lt 1 ]; then
	echo "Usage: `basename $0` username"
	exit 1
fi
if ! id -u $1 &> /dev/null; then
	echo "Usage: `basename $0` username"
	echo "No this user $1."
	exit 2
fi

if [ $(id -u $1) -eq 0 ]; then
	echo "Admin"
elif [ $(id -u $1) -ge 500 ]; then
	echo "Common user."
else
	echo "System user."
fi

條件測試之case語句

case語句:有多個測試條件時,case語句會使得語法結構更明晰

語句結構:

case 變量引用 in
PATTERN1)
	分支1
;;
PATTERN2)
	分支2
;;
...
*)
	分支n
;;
esac

PATTERN:類同于文件名通配機制,但支持使用|表示或者

a|b: a或者b
*:匹配任意長度的任意字符
?: 匹配任意單個字符
[]: 指定范圍內的任意單個字符

例:寫一個腳本,完成如下任務,其使用形式如下所示:

script.sh {start|stop|restart|status}

其中:

如果參數為空,則顯示幫助信息,并退出腳本;

如果參數為start,則創建空文件/var/lock/subsys/script,并顯示“starting script successfully.”

如果參數為stop,則刪除文件/var/lock/subsys/script,并顯示“Stop script successfully.”

如果參數為restart,則刪除文件/var/locksubsys/script并重新創建,而后顯示“Restarting script successfully.”

如果參數為status,那么:如果文件/var/lock/subsys/script存在,則顯示“Script is running…”,否則,則顯示“Script is stopped.”

#!/bin/bash
file='/var/lock/subsys/script'
case $1 in
start)
  if [ -f $file ];then
	echo "Script is running..."
  	exit 3
  else
	touch $file
	[ $? -eq 0 ] && echo "Starting script successfully."
  fi
  ;;
stop)
  if [ -f $file ];then
	rm -rf $file
	[ $? -eq 0 ] && echo "Stop script successfully."
  else
	echo "Script is stopped..."
	exit 4
  fi
  ;;
restart)
  if [ -f $file ];then
	rm -rf $file
	[ $? -eq 0 ] && echo "Stop script successfully"
  else 
	echo "Script is stopped..."
	exit 5
  fi
	touch $file
	[ $? -eq 0 ] && echo "Starting script successfully"
  ;;
status)
  if [ -f $file ];then
	echo "Script is running..."
  else
	echo "Script is stopped."
  fi
  ;;
*)
	echo "`basename $0` {start|stop|restart|status}"
	exit 2
  ;;
  esac

bash編程之循環語句

循環之for循環

for語句格式一

語句結構:

for 變量名 in 列表; do
    循環體
done

列表:可包含一個或多個元素

循環體:依賴于調用變量來實現其變化

循環可嵌套

退出條件:遍歷元素列表結束

例:求100以內所有正整數之和

#!/bin/bash
declare -i sum=0
for i in {1..100}; do
    let sum+=$i
done
echo $sum

for語句格式二

for ((初始條件;測試條件;修改表達式)); do
      循環體
done

先用初始條件和測試條件做判斷,如果符合測試條件則執行循環體,再修改表達式,否則直接跳出循環。

例:求100以內所有正整數之和(for二實現)

#!/bin/bash
declare -i sum=0
for ((counter=1;$counter <= 100; counter++)); do
	let sum+=$counter
done
echo $sum

循環之while語句

while適用于循環次數未知,或不便用for直接生成較大的列表時

語句結構:

while 測試條件; do
	循環體
done

測試條件為真,進入循環;測試條件為假,退出循環

例:求100以內所有偶數之和,要求使用取模方法

#!/bin/bash
declare -i counter=1
declare -i sum=0
while [ $counter -le 100 ]; do
	if [ $[$counter%2] -eq 0 ]; then
		 let sum+=$counter
	fi
	let counter++
done
echo $sum

例:提示用戶輸入一個用戶名,如果用戶存在,就顯示用戶的ID號和shell;否則顯示用戶不存在;顯示完成之后不退出,再次重復前面的操作,直到用戶輸入q或quit為止

#!/bin/bash
read -p "Plz enter a username: " userName
while [ "$userName" != 'q' -a "$userName" != 'quit' ]; do
	if id $userName &> /dev/null; then
	   grep "^$userName\>" /etc/passwd | cut -d: -f3,7
	else
		echo "No such user."
	fi
read -p "Plz enter a username again: " userName
done

while特殊用法:遍歷文本文件

語句結構:

while read 變量名; do
	循環體
done < /path/to/somefile

變量名,每循環一次,記憶了文件中一行文本

例:顯示ID號為偶數,且ID號同GID的用戶的用戶名、ID和SHELL

while read line; do
	userID=`echo $line | cut -d: -f3`
	groupID=`echo $line | cut -d: -f4`
	if [ $[$userID%2] -eq 0 -a $userID -eq $groupID ]; then
		 echo $line | cut -d: -f1,3,7
	fi
done < /etc/passwd

循環之until語句

語句結構:

until 測試條件; do
      循環體
done

測試條件為假,進入循環;測試條件為真,退出循環

例:求100以內所有偶數之和,要求使用取模方法(until實現)

#!/bin/bash
declare -i counter=1
declare -i sum=0
until [ $counter -gt 100 ]; do
	if [ $[$counter%2] -eq 0 ]; then
		 let sum+=$counter
	fi
	let counter++
done
echo $sum

例:提示用戶輸入一個用戶名,如果用戶存在,就顯示用戶的ID號和shell;否則顯示用戶不存在;顯示完成之后不退出,再次重復前面的操作,直到用戶輸入q或quit為止(until實現)

#!/bin/bash
read -p "Plz enter a username: " userName
until [ "$userName" = 'q' -a "$userName" = 'quit' ]; do
	if id $userName &> /dev/null; then
	   grep "^$userName\>" /etc/passwd | cut -d: -f3,7
	else
		echo "No such user."
	fi
read -p "Plz enter a username again: " userName
done

循環之循環控制和shift

循環控制命令:

break:提前退出循環

break [N]: 退出N層循環;N省略時表示退出break語句所在的循環

continue: 提前結束本輪循環,而直接進入下輪循環

continue [N]:提前第N層的循環的本輪循環,而直接進入下輪循環

死循環:

#while體
while true; do
      循環體
done
#until體
until false; do
      循環體
done

例:寫一個腳本,判斷給定的用戶是否登錄了當前系統

(1) 如果登錄了,則腳本終止;

(2) 每5秒種,查看一次用戶是否登錄;

#!/bin/bash
while true; do
    who | grep "gentoo" &> /dev/null
    if [ $? -eq 0 ];then
break
    fi
    sleep 5
done
echo "gentoo is logged."

shift:如果沒有數字,只有shift 就是跳過一個參數獲取下一個參數,如果加上數字,比如shift 2 ,跳過兩個參數獲取下一個參數。

例:寫一個腳本,使用形式如下所示    

    showifinfo.sh [-i INTERFACE|-a] [-v]

    要求:

    1、-i或-a不可同時使用,-i用于指定特定網卡接口,-a用于指定所有接口;

    顯示接口的ip地址

    2、使用-v,則表示顯示詳細信息

    顯示接口的ip地址、子網掩碼、廣播地址;

    3、默認表示僅使用-a選項;

#!/bin/bash
allinterface=0
ifflag=0
verbose=0
interface=0
if [ $# -eq 0 ];then
	ifconfig | grep "inet addr:" | awk '{print $2}'
fi
while [ $# -ge 1 ];do
  case $1 in
  -a)
	allinterface=1
	shift 1
  ;;
  -i)
	ifflag=1
	interface=$2
	shift 2
  ;;
  -v)
	verbose=1
	shift 1
  ;;
  *)
	echo "error option"
	exit 2
  ;;
  esac
done
if [ $allinterface -eq 1 ];then
  if [ $ifflag -eq 1 ];then
  	echo "command not found"
  	exit 5
  fi
  if [ $verbose -eq 1 ];then
  	ifconfig | grep "inet addr:"
  else
  	ifconfig | grep "inet addr:" | awk '{print $2}'
  fi
fi
if [ $ifflag -eq 1 ];then
  if [ $allinterface -eq 1 ];then
        echo "command not found"
        exit 5
  fi
  if [ $verbose -eq 1 ];then
  	ifconfig $interface | grep "inet addr:"
  else
  	ifconfig $interface | grep "inet addr:" | awk '{print $2}'
  fi
fi

bash編程之函數

語法結構:

function F_NAME {
		函數體
	}

	F_NAME() {
		函數體
	}

可調用:使用函數名,函數名出現的地方,會被自動替換為函數

函數的返回值:

      函數的執行結果返回值:代碼的輸出

            函數中使用打印語句:echo, printf

            函數中調用的系統命令執行后返回的結果

      執行狀態返回值:

            默認取決于函數體執行的最后一個命令狀態結果

            自定義退出狀態碼:return [0-255]

            注意:函數體運行時,一旦遇到return語句,函數即返回;

函數可以接受參數:

在函數體中調用函數參數的方式同腳本中調用腳本參數的方式:位置參數

$1, $2, …

$#, $*, $@

例:寫一個腳本,完成如下功能(使用函數):

1、提示用戶輸入一個可執行命令;

2、獲取這個命令所依賴的所有庫文件(使用ldd命令);

3、復制命令至/mnt/sysroot/對應的目錄中

解釋:假設,如果復制的是cat命令,其可執行程序的路徑是/bin/cat,那么就要將/bin/cat復到/mnt/sysroot/bin/目錄中,如果復制的是useradd命令,而useradd的可執行文件路徑為/usr/sbin/useradd,那么就要將其復制到/mnt/sysroot/usr/sbin/目錄中;

4、復制各庫文件至/mnt/sysroot/對應的目錄中;

#!/bin/bash
#
target=/mnt/sysroot/

[ -d $target ] || mkdir $target

preCommand() {
    if which $1 &> /dev/null; then
	commandPath=`which --skip-alias $1`
	return 0
    else
	echo "No such command."
	return 1
    fi
}

commandCopy() {
    commandDir=`dirname $1`
    [ -d ${target}${commandDir} ] || mkdir -p ${target}${commandDir}
    [ -f ${target}${commandPath} ] || cp $1 ${target}${commandDir}
}

libCopy() {
    for lib in `ldd $1 | egrep -o "/[^[:space:]]+"`; do
	libDir=`dirname $lib`
	[ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}
	[ -f ${target}${lib} ] || cp $lib ${target}${libDir}
    done
} 

read -p "Plz enter a command: " command

until [ "$command" == 'quit' ]; do

  if preCommand $command &> /dev/null; then
    commandCopy $commandPath
    libCopy $commandPath
  fi

  read -p "Plz enter a command: " command
done

bash編程之信號捕捉

trap命令用于在shell程序中捕捉到信號,之后可以有三種反應方式:

(1)執行一段程序來處理這一信號

(2)接受信號的默認操作

(3)忽視這一信號

trap對上面三種方式提供了三種基本形式:

第一種形式的trap命令在shell接收到signal list清單中數值相同的信號時,將執行雙引號中的命令串。

trap 'commands' signal-list

trap "commands" signal-list

第二種形式的trap命令恢復信號的默認操作:trap signal-list

第三種形式的trap命令允許忽視信號:trap " " signal-list

trap 'COMMAND' SIGINT(表示關閉進程)

例:寫一個腳本,能夠ping探測指定網絡內的所有主機是否在線,當沒有執行完時可接收ctrl+c命令退出。

#!/bin/bash

quitScript() {
	 echo "Quit..."
}    
trap 'quitScript; exit 5' SIGINT

cnetPing() {
	for i in {1..254}; do
		if ping -c 1 -W 1 $1.$i &> /dev/null; then
			echo "$1.$i is up."
		 else
			echo "$1.$i is down."
		fi
		done
}

bnetPing() {
	for j in {0..255}; do
		cnetPing $1.$j 
	done
}

anetPing() {
	for m in {0..255}; do
		bnetPing $1.$m
	done
}

netType=`echo $1 | cut -d"." -f1`

if [ $netType -ge 1 -a $netType -le 126 ]; then
	anetPing $netType
elif [ $netType -ge 128 -a $netType -le 191 ]; then
	bnetPing $(echo $1 | cut -d'.' -f1,2)
elif [ $netType -ge 192 -a $netType -le 223 ]; then
	cnetPing $(echo $1 | cut -d'.' -f1-3)
else
	echo "Wrong"
	exit 2
fi

bash編程之數組

數組:連續的多個獨立內存空間,每個內存空間相當于一個變量

數組元素:數組名+索引(從0開始編號)

索引的表示方式:a[0], a[1]

聲明數組:declare -a ARRAR_NAME

關聯數組:declare -A ARRAY_NAME

支持稀疏格式:僅一維數組  

數組元素的賦值:

(1) 一次只賦值一個元素

a[0]=$RANDOM

(2) 一次賦值全部元素

a=(red blue yellow green)

(3) 指定索引進行賦值

a=([0]=green [3]=red [2]=blue [6]=yellow)

(4) 用戶輸入

read -a ARRAY

數組的訪問:

用索引訪問:ARRAY[index]

數組的長度:

${#ARRAY[*]}

${#ARRAY[@]}

例:寫一個腳本,生成10個隨機數,保存至數組中;而后顯示數組下標為偶數的元素

#!/bin/bash
for i in {0..9}; do
    rand[$i]=$RANDOM
    [ $[$i%2] -eq 0 ] && echo "$i:${rand[$i]}"
done

從數組中挑選某元素:

${ARRAY[@]:offset:number}

切片:

offset: 偏移的元素個數

number: 取出的元素的個數

${ARRAY[@]:offset}:取出偏移量后的所有元素

${ARRAY[@]}: 取出所有元素

數組復制:

要使用${ARRAY[@]}

$@: 每個參數是一個獨立的串

$*: 所有參數是一個串

向數組中追加元素:非稀疏格式

week, 

week[${#week[@]}]

從數組中刪除元素:

unset ARRAY[index]

例:復制一個數組中下標為偶數的元素至一個新數組中

#!/bin/bash
declare -a mylogs
logs=(/var/log/*.log)
echo ${logs[@]}
for i in `seq 0 ${#logs[@]}`; do
	if [ $[$i%2] -eq 0 ];then
		index=${#mylogs[@]}
		 mylogs[$index]=${logs[$i]}
	fi
done
echo ${mylogs[@]}

例:生成10個隨機數,升序排序

#!/bin/bash
for((i=0;i<10;i++))
do
	rnd[$i]=$RANDOM
done
echo -e "total=${#rnd[@]}\n${rnd[@]}\nBegin to sort"
for((i=9;i>=1;i--))
do
        for((j=0;j<i;j++))
	do
	if [ ${rnd[$j]} -gt ${rnd[$[$j+1]]} ] ;then
		swapValue=${rnd[$j]}
		rnd[$j]=${rnd[$[$j+1]]}
		rnd[$[$j+1]]=$swapValue		
	fi
	done
done
echo ${rnd[@]}

例:打印九九乘法表

#!/bin/bash
for((i=1;i<=9;i++))
do 
strLine=""
	for((j=1;i<=9;j++))
	do
		strLine=$strLine"$i*$j="$[$i*$j]"\t"
		[ $i -eq $j ] && echo -e $strLine && break
	done
done

bash編程之字符串操作

字符串切片:

${string:offset:length}

[root@scholar scripts]# string='hello word'
[root@scholar scripts]# echo ${string:2:4}
llo

取尾部的指定個數的字符:

${string: -length}

[root@scholar scripts]# echo ${string: -2}
rd

取子串:基于模式

${variable#*word}:在variable中存儲字串上,自左而右,查找第一次出現word,刪除字符開始至此word處的所有內容;

${variable##*word}:在variable中存儲字串上,自左而右,查找最后一次出現word,刪除字符開始至此word處的所有內容;

file='/var/log/messages'
${file#*/}: 返回的結果是var/log/messages
${file##*/}: 返回messages

${variable%word*}: 在variable中存儲字串上,自右而左,查找第一次出現word,刪除此word處至字串尾部的所有內容;

${variable%%world*}:在variable中存儲字串上,自右而左,查找最后一次出現word,刪除此word處至字串尾部的所有內容;

file='/var/log/messages'
${file%*/}: 返回的結果是/var/log
${file%%*/}: 返回結果為空

例:url="http://www.redhat.com:80"

取端口:${url##*:}
取協議:${url%%:*}

查找替換:

${variable/pattern/substi}: 替換第一次出現

#userinfo=`tail -1 /etc/passwd
#echo $userinfo
scholar:x:500:500:scholar:/home/scholar:/bin/bash
#echo ${userinfo/scholar/redhat}
redhat:x:500:500:scholar:/home/scholar:/bin/bash

${variable//pattern/substi}:替換所有的出現

#echo ${userinfo//scholar/redhat}
redhat:x:500:500:redhat:/home/redhat:/bin/bash

${variable/#pattern/substi}:替換行首被pattern匹配到的內容

#echo ${userinfo/#scholar/redhat}
redhat:x:500:500:scholar:/home/scholar:/bin/bash

${variable/%pattern/substi}:替換行尾被pattern匹配到的內容

#echo ${userinfo/%bash/redhat}
scholar:x:500:500:scholar:/home/scholar:/bin/redhat

pattern可以使用globbing中的元字符:* ?

查找刪除:

${variable/pattern}:刪除第一次出現

#echo ${userinfo/scholar}
:x:500:500:scholar:/home/scholar:/bin/bash

${variable//pattern}:刪除所有的出現

#echo ${userinfo//scholar}
:x:500:500::/home/:/bin/bash

${variable/#pattern}:刪除行首被pattern匹配到的內容

#echo ${userinfo/#scholar}
:x:500:500:scholar:/home/scholar:/bin/bash

${variable/%pattern}:刪除行尾被pattern匹配到的內容

#echo ${userinfo/%bash}
scholar:x:500:500:scholar:/home/scholar:/bin/

大小寫轉換:

小–>大:${variable^^}

#echo ${userinfo^^}
SCHOLAR:X:500:500:SCHOLAR:/HOME/SCHOLAR:/BIN/BASH

大–>?。?{variable,,}

#name="SCHOLAR"
#echo ${name,,}
scholar

變量賦值操作:

${variable:-string}:variable為空或未設定,那么返回string,否則,返回variable變量的值;

${variable:=string}:variable為空或未設定,則返回string,且將string賦值給變量variable,否則,返回variable的值;

為腳本使用配置文件,并確保某變量有可用值的方式

variable=${variable:-default vaule}

寫個腳本,配置etc目錄;

(1) 在配置文件中定義變量;

(2) 在腳本中source配置文件;

#!/bin/bash
[ -f /etc/sysconfig/network ] && source /etc/network/network
[-z "$HOSTAME" -o "$HOSTNAME" = '(none)' ] || HOSTNAME ='localhost'
/bin/hostname $HOSTNAME
/bin/hostname

bash編程之補充

mktemp命令:

mktemp [OPTIONS] filename.XXX

-d: 創建臨時目錄
--tmpdir=/path/to/somewhere :指定臨時文件所在的目錄
mktemp /tmp/tmp.XXX                    #XXX生成相同數量隨機字符
mktemp --tmpdir=/var/tmp tmp.XXX       #指定目錄創建臨時文件
mktemp --tmpdir=/var/tmp -d tmp.XXX    #指定目錄創建臨時目錄

install命令:

install [OPTIONS] SOURCE DEST

install [OPTIONS] SOURCE… DIR

install [OPTIONS] -d DIR …

增強型的復制命令:

-o OWNER
-g GROUP
-m MODE
-d : 創建目錄
install /etc/fstab /tmp                 #復制文件到指定目錄
install --mode=644 /etc/fstab /tmp/     #復制時指定權限
install --owner=scholar /etc/fstab /tmp #復制時指定屬主
install --group=scholar /etc/fstab /tmp #復制時指定屬組
install -d /tmp/install                 #創建目錄

The end

至此,bash編程的所有基礎語法知識點就總結完畢了,掌握了以上知識點,bash編程算是略有小成了吧,如果有興趣可繼續鉆研高級語法,目前能力不足就不介紹啦。這里給大家推薦兩本bash編程的書籍,能力相對較弱的可以看一下《Linux命令行和shell編程寶典》,有能力的就看《abs-guide》吧。看在碼字辛苦的份上,多多點贊吧。

以上僅為個人學習總結,如有錯漏,大神勿噴~~~

原創文章,作者:書生,如若轉載,請注明出處:http://www.www58058.com/2597

(1)
書生書生
上一篇 2015-04-04
下一篇 2015-04-05

相關推薦

  • 馬哥教育網絡班21期+第13周課程練習

    1、建立samba共享,共享目錄為/data,要求:(描述完整的過程) 1)共享名為shared,工作組為magedu; 2)添加組develop,添加用戶gentoo,centos和ubuntu,其中gentoo和centos以develop為附加組,ubuntu不屬于develop組;密碼均為用戶名; 3)添加samba用戶gentoo,centos和u…

    Linux干貨 2016-10-24
  • btrfs文件系統

                                                      &nbsp…

    Linux干貨 2015-08-21
  • 磁盤配額

    磁盤配額 1 啟用磁盤配額 首先創建新的分區 /dev/sd5,并創建文件系統。 [root@local ~]# mkfs.ext4 /dev/sda5 由于xfs 不磁盤配額能成功,這里使用ext4. 然后把/dev/sda5分區掛載到 /home [root@local ~]# mount /dev/sda5 /home [root@local ~]# …

    Linux干貨 2017-05-02
  • SSH協議詳解

    OpenSSH 一、 前言 使用SSH可以在本地主機和遠程服務器之間進行加密地傳輸數據,實現數據的安全。而OpenSSH是SSH協議的免費開源實現,它采用安全、加密的網絡連接工具代替了telnet、ftp等古老明文傳輸工具。 SSH(Secure Shell)是建立在應用層和傳輸層基礎上的安全協議。SSH是目前較可靠,專為遠程登陸會話和其他網絡服務提供安全性…

    Linux干貨 2016-12-16
  • M20 – 1- 第三周博客(3):Linux上文本處理三劍客grep

    Grep是一種強大的文本搜索工具,它能使用正則表達式搜索文本,并把匹配的行打印出來。 1、作用 Linux系統中grep命令是一種強大的文本搜索工具,它能使用正則表達式搜索文本,并把匹 配的行打印出來。grep全稱是Global Regular Expression Print,表示全局正則表達式版本,它的使用 權限是…

    Linux干貨 2016-08-08
  • Linux用戶與權限管理

    由于Linux是多用戶、多任務系統,出于一些需要,當我們創建的文件希望對一部分用戶開放,對一部分用戶隱藏的時候應該怎么辦呢?這樣的話,就需要涉及到Linux系統中對用戶以及對文件權限的管理。 一、相關文件 在Linux中,一切配置文件都是以文本文檔的方式來保存的,同樣用戶的信息也保存在系統的一些文件中,其位置為/etc/passwd。此文件只有root用戶具…

    Linux干貨 2016-08-05

評論列表(1條)

  • stanley
    stanley 2015-04-04 22:44

    哇哦,書生快成咱們博客之星了,文檔功夫相當扎實深厚,有空了可以和同學們介紹下寫文檔的技巧

欧美性久久久久