以前寫了系列的shell實戰的文章,獲得了挺多小夥伴的關注,遇到有些對shell不太熟悉小夥伴,因此有個想法寫一篇shell入門的文章。
時間流逝,再回頭去看看過去的東西,纔會發現哪些東西比較重要,故撰此文,記錄我在過去學習和使用shell語言過程當中我我的以爲比較重要的部分,作一個小總結和分享。git
文章中使用到的代碼位置: gitee.com/dhar/YTTInj…
和
gitee.com/dhar/ShellL…github
文章內容結構以下:正則表達式
語法shell
文件數組
sed流編輯ruby
模塊bash
輸入和菜單less
定義一個變量和其餘語言的相似,shell是弱類型語言因此不須要使用類型限定,而且變量能夠修改類型,下面的例子定義了一個字符串類型的str
變量,以後修改成數值類型curl
注意點:變量等號兩邊不能有空格出現函數
str="string"
echo $str
echo ${str}
str=123
echo $str
複製代碼
變量能夠賦值給另外一個變量和打印,當變量被使用的時候須要在變量名稱前面加上$
符號,還有另外一種方式是把變量名放在${}
括號中使用,能夠把命令執行結果做爲右值賦值給變量
str2=$str
echo $str2;
str3=${str}
echo ${str3}
curDir=$(pwd)
echo "curDir = ${curDir}"
curDirCon=`ls`
echo "curDirCon = ${curDir2}"
# 輸出:
=======變量=======
string
string
123
123
123
curDir = /Users/aron/git-repo/ShellLearning/helloshell
curDirCon = data
syntax.sh
複製代碼
由於shell沒有單步調試和其餘功能強大的IDE,因此打印功能就常用到,此外打印功能還能夠當作函數的返回值,比return做爲函數的返回值功能更強大,shell 使用echo
打印,內容默認輸出到控制檯中,echo
能夠打印字符串、變量、以及字符串中嵌入變量的混個內容,echo
有幾重要的參數選項
\t
顯示爲製表符而不是顯示輸出\t
str4="string4"
echo $str4
echo "str4=$str4"
echo "str4=${str4}str3=${str3}"
# 輸出:
=======打印=======
string4
str4=string4
str4=string4str3=123
複製代碼
expr
執行算術運算注意點:*
乘法運算符號須要轉義
echo "=======運算======="
result=$(expr 5 + 5)
echo ${result}
result=$(expr 16 - 5)
echo ${result}
result=$(expr 5 \* 5)
echo ${result}
result=$(expr 28 / 5)
echo ${result}
# 輸出:
=======expr運算=======
10
11
25
5
複製代碼
[]
執行算術[]
執行算術比expr
簡單多了,而且*
乘法運算符號不須要轉義
echo "=======[]運算======="
result=$[5 + 5]
echo ${result}
result=$[16 - 5]
echo ${result}
result=$[5 * 5]
echo ${result}
result=$[28 / 5]
echo ${result}
# 輸出:
=======[]運算=======
10
11
25
5
複製代碼
控制使用if
/else
/fi
語法,典型的數值比較以下
if [[ 3 > 7 ]]; then
echo "hehe"
else
echo "yes"
fi
# 輸出:
yes
複製代碼
還可使用下面的比較符號
比較符 | 描述 |
---|---|
n1 -eq n2 | 檢查n1是否與n2相等 |
n1 -ge n2 | 檢查n1是否大於或等於n2 |
n1 -gt n2 | 檢查n1是否大於n2 |
n1 -le n2 | 檢查n1是否小於或等於n2 |
n1 -lt n2 | 檢查n1是否小於n2 |
n1 -ne n2 | 檢查n1是否不等於n2 |
一個簡單的9*9乘法口訣表的例子
echo "9*9======="
i=1
j=1
line=""
while [[ i -lt 10 ]]; do
j=1
line=""
until [[ j -eq 10 ]]; do
if [[ j -le i ]]; then
result=$(expr $i \* $j)
resultStr="$j X $i = $result"
line=${line}${resultStr}"\t"
fi
j=$(expr $j + 1)
done
echo -e ${line}
i=$(expr $i + 1)
done
# 輸出:
9*9=======
1 X 1 = 1
1 X 2 = 2 2 X 2 = 4
1 X 3 = 3 2 X 3 = 6 3 X 3 = 9
1 X 4 = 4 2 X 4 = 8 3 X 4 = 12 4 X 4 = 16
1 X 5 = 5 2 X 5 = 10 3 X 5 = 15 4 X 5 = 20 5 X 5 = 25
1 X 6 = 6 2 X 6 = 12 3 X 6 = 18 4 X 6 = 24 5 X 6 = 30 6 X 6 = 36
1 X 7 = 7 2 X 7 = 14 3 X 7 = 21 4 X 7 = 28 5 X 7 = 35 6 X 7 = 42 7 X 7 = 49
1 X 8 = 8 2 X 8 = 16 3 X 8 = 24 4 X 8 = 32 5 X 8 = 40 6 X 8 = 48 7 X 8 = 56 8 X 8 = 64
1 X 9 = 9 2 X 9 = 18 3 X 9 = 27 4 X 9 = 36 5 X 9 = 45 6 X 9 = 54 7 X 9 = 63 8 X 9 = 72 9 X 9 = 81
======= =======
複製代碼
比較符 | 描述 |
---|---|
str1 = str2 | 檢查str1是否和str2相同 |
str1 != str2 | 檢查str1是否和str2不一樣 |
str1 < str2 | 檢查str1是否比str2小 |
str1 > str2 | 檢查str1是否比str2大 |
-n str1 | 檢查str1的長度是否非0 |
-z str1 | 檢查str1的長度是否爲0 |
echo "=======控制字符串比較======="
str1="abc"
str2="abd"
if [[ $str1 > $str2 ]]; then
echo "$str1 大於 $str2"
else
echo "$str1 小於等於 $str2"
fi
if [[ -z $str1 ]]; then
echo "str1 爲空"
else
echo "str1 不爲空"
fi
str1=""
if [[ -z $str1 ]]; then
echo "str1 爲空"
else
echo "str1 不爲空"
fi
# 輸出:
=======控制字符串比較=======
abc 小於等於 abd
str1 不爲空
str1 爲空
複製代碼
比較符 | 描述 |
---|---|
-d file | 檢查file是否存在並是一個目錄 |
-e file | 檢查file是否存在 |
-f file | 檢查file是否存在並是一個文件 |
-r file | 檢查file是否存在並可讀 |
-s file | 檢查file是否存在並不是空 |
-w file | 檢查file是否存在並可寫 |
-x file | 檢查file是否存在並可執行 |
-O file | 檢查file是否存在並屬當前用戶全部 |
-G file | 檢查file是否存在而且默認組與當前用戶相同 |
file1 -nt file2 | 檢查file1是否比file2新 |
file1 -ot file2 | 檢查file1是否比file2舊 |
echo "=======控制文件比較======="
file="syntax.sh"
if [[ -e $file ]]; then
echo "${file} 文件存在"
else
echo "${file} 文件不存在"
fi
if [[ -f $file ]]; then
echo "${file} 是一個文件"
else
echo "${file} 不是一個文件"
fi
if [[ -d $file ]]; then
echo "${file} 是一個文件夾"
else
echo "${file} 不是一個文件夾"
fi
# 輸出:
=======控制文件比較=======
syntax.sh 文件存在
syntax.sh 是一個文件
syntax.sh 不是一個文件夾
複製代碼
echo "=======循環for======="
num=0
for (( i = 0; i < 10; i++ )); do
num=$[$num + $i]
done
echo "result = ${num}"
# 輸出:
=======循環for=======
result = 45
複製代碼
data
文件內容以下:
➜ helloshell git:(master) ✗ cat data
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.%
複製代碼
echo "=======循環for in======="
file="data"
IFS_OLD=$IFS
IFS=$'\n'
for line in $(cat $file)
do
echo "${line}"
done
IFS=${IFS_OLD}
# 輸出:
=======循環for in=======
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
複製代碼
while
表示條件知足執行循環,好比下面的例子是9*9乘法口訣表中的一部分,表示i從1循環到9
i=1
while [[ i -lt 10 ]]; do
i=$(expr $i + 1)
done
複製代碼
until
和while
相反,表示條件不知足執行循環,好比下面的例子是9*9乘法口訣表中的一部分,表示j從1循環到9
j=1
line=""
until [[ j -eq 10 ]]; do
if [[ j -le i ]]; then
result=$(expr $i \* $j)
resultStr="$j X $i = $result"
line=${line}${resultStr}"\t"
fi
j=$(expr $j + 1)
done
echo -e ${line}
複製代碼
數組的定義以下 declare -a array_name
注意:osx系統由於bash
的版本過低,只能定義索引數組,在bash
版本高於4.1的版本可使用declare -A array_name
定義關聯數組
如下的代碼片定義一個數組,用於保存配置文件中的內容,而後使用for循環遍歷數組內容輸出到控制檯。
####### 數據定義
# 定義保存類名稱的數組
declare -a config_content_array
cfg_line_count=0
# 一、讀取配置文件內容保存到數組中
read_config_content_to_array() {
# 讀取配置文件
echo "開始讀取配置文件..."
# mark: p291
IFS_OLD=$IFS
IFS=$'\n'
# 刪除文件行首的空白字符 http://www.jb51.net/article/57972.htm
for line in $(cat $cfg_file | sed 's/^[ \t]*//g')
do
is_comment=$(expr "$line" : '^#.*')
echo "line=${line} is_common=${is_comment}"
if [[ ${#line} -eq 0 ]] || [[ $(expr "$line" : '^#.*') -gt 0 ]]; then
echo "blank line or comment line"
else
config_content_array[$cfg_line_count]=$line
cfg_line_count=$[ $cfg_line_count + 1 ]
echo "line>>>>${line}"
fi
done
IFS=${IFS_OLD}
for (( i = 0; i < ${#config_content_array[@]}; i++ )); do
config_content=${config_content_array[i]};
echo "config_content>>>>>>${config_content}"
done
}
複製代碼
方法的定義有兩種方式
方法返回值的處理有三種方式
方法的參數
echo "=======方法======="
function func1 {
echo "func1 invoked"
# 最大的返回值爲256,超過了256取模的結果,280%256=24,最終返回24
return 280;
}
func2() {
echo "return value"
}
# 檢測文件夾存在的方法,結果保存在全局變量`CheckInputDestDirRecursiveReturnValue`中
# 參數一:檢測的文件夾路徑
# 參數二:提示消息字符串
# 使用方式以下,去掉註釋
# # 導入工具腳本
# . ./FileUtil.sh
# # 檢測class_search_dir
# checkDirCore $class_search_dir "指定類的查找目錄不存在"
# class_search_dir=${CheckInputDestDirRecursiveReturnValue}
checkDirCore() {
to_process_dir=$1
message=$2
echo "scriptName=${0} paramsCount=${#}"
# 需處理源碼目錄檢查
if [[ -d $to_process_dir ]]; then
echo "目錄存在 $to_process_dir"
CheckInputDestDirRecursiveReturnValue=$to_process_dir
return 1
else
echo "${message} ${to_process_dir}"
checkInputDestDirRecursive ${to_process_dir}
fi
}
echo `func1`
echo `func2`
func1
retValue=$?
echo "func1 retValue=$retValue"
retValue=`func2`
echo "func2 retValue=$retValue"
checkDirCore $(pwd) "指定類的查找目錄不存在"
dir=${CheckInputDestDirRecursiveReturnValue}
echo "dir = ${dir}"
# 輸出:
=======方法=======
func1 invoked
return value
func1 invoked
func1 retValue=24
func2 retValue=return value
scriptName=./syntax.sh paramsCount=2
目錄存在 /Users/aron/git-repo/ShellLearning/helloshell
dir = /Users/aron/git-repo/ShellLearning/helloshell
複製代碼
文件的讀取可使用cat
命令結合for in
循環處理
注意:'\n'`,處理完成以後恢復舊值
echo "=======文件======="
file="data"
IFS_OLD=$IFS
IFS=$'\n'
for line in $(cat $file)
do
echo "${line}"
done
IFS=${IFS_OLD}
輸出:
=======文件=======
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
複製代碼
文件的讀取可使用ls
命令結合for in
循環處理
echo "=======文件目錄======="
function read_implement_file_recursively {
if [[ -d $1 ]]; then
for item in $(ls $1); do
itemPath="$1/${item}"
if [[ -d $itemPath ]]; then
# 目錄
echo "處理目錄 ${itemPath}"
read_implement_file_recursively $itemPath
else
# 文件
echo "處理文件 ${itemPath}"
fi
done
else
echo "err:不是一個目錄"
fi
}
read_implement_file_recursively $(pwd)
輸出:
=======文件目錄=======
處理文件 /Users/aron/git-repo/ShellLearning/helloshell/data
處理目錄 /Users/aron/git-repo/ShellLearning/helloshell/subfolder
處理文件 /Users/aron/git-repo/ShellLearning/helloshell/subfolder/data2
處理文件 /Users/aron/git-repo/ShellLearning/helloshell/syntax.sh
複製代碼
使用輸出重定向把內容輸出到文件
>
輸出重定向符號先清空文件而後把內容寫入到文件中>>
輸出重定向符號把內容追加寫入到文件中此外能夠結合其餘命令實現排序、去重功能
sort
命令對文件內容以行做爲單位排序uniq
命令對文件內容進行去重,以行爲單位,通常須要結合sort
命令使用file="subfolder/data2"
destfile="subfolder/data2-p"
sort ${file} | uniq > ${destfile}
結果:
➜ helloshell git:(master) ✗ cat subfolder/data2
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown
fox
jumps over the lazy dog.%
➜ helloshell git:(master) ✗ cat subfolder/data2-p
The quick brown
The quick brown fox jumps over the lazy dog.
fox
jumps over the lazy dog.
複製代碼
Sed流編輯結合正則表達式能夠方便的對文本文件進行查詢、修改、刪除、增長等操做
注意:osx系統自帶的sed命令和標準的gun-sed使用方式上有些差異,因此如下篇幅所談論到的sed都是標準的gun-sed,下面的這個腳本用戶判斷系統是否安裝了gun-sed,若是沒有回自動進行安裝,完成以後須要用戶執行顯示的顯示的命令配置下便可。
# 檢測是否安裝gun sed,mac 內置的sed會有些問題,因此須要安裝gun sed
gunSedInstallCheck() {
# 檢查是否安裝gunsed
# mac安裝gunSed http://blog.csdn.net/sun_wangdong/article/details/71078083
which_sed=`which sed`
echo $which_sed
echo "testresult = $(expr "$which_sed" : '.*/gnu-sed/')"
which_sed=`ls -al ${which_sed}`
echo $which_sed
echo "testresult = $(expr "$which_sed" : '.*/gnu-sed/')"
if [[ $(expr "$which_sed" : '.*/gnu-sed/') -gt 0 ]]; then
echo "檢測到使用gun sed"
else
if [ ! `which brew` ]
then
echo 'Homebrew not found. Trying to install...'
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \
|| exit 1
fi
echo 'Trying to install gun sed...'
brew install gnu-sed --with-default-names || exit 1
# 設置局部環境變量
echo "set PATH...."
source ./set-gun-sed-path.sh
echo "set PATH done"
echo "請手動執行命令,而後從新執行"
command="PATH=\"/usr/local/Cellar/gnu-sed/4.4/bin:\$PATH\""
echo $command
echo ""
exit 1
fi
}
複製代碼
sed
命令功能繁多,因此這裏只講講我在實戰中使用到的,首先了解小sed命令的結構
sed -param operation/pattern/replacement/flags
查找對應的模式和匹配模式的替換內容
有4種可用的替換標記:
如下是injectContentShell#injectedContentShell.sh
腳本文件中的代碼片斷,使用a
操做吧內容添加到方法的開頭
/^- \(.*\){$/
這部分是pattern
,匹配OC中方法的開始a\ '"$injected_content"'
這部分是operation
,注意其中插入內容的變量要使用雙引號和單引號包含處理# 在匹配的行下面添加插入內容
sed -i '/^- \(.*\){$/{ a\ '"$injected_content"' }' ${file}
複製代碼
如下是injectContentShell#injectedContentShell.sh
腳本文件中的代碼片斷,使用d
操做刪除內容
sed -i '/'"$pattern_str"'/ { d }' ${file}
複製代碼
如下是injectContentShell#RenameClasses.sh
腳本文件中的代碼片斷,使用s
操做替換內容,有如下幾個要點
s/'"${original_class_name}"'/'"${result_class_name}"'/g
,使用s
操做,注意pattern
和replacement
中變量的處理方式,使用雙引號、單引號雙重包含,使用flag
爲g
表示所有替換grep ${original_class_name} -rl ${pbxproj_dir}
,grep
命令查找${pbxproj_dir}
文件夾下全部出現${original_class_name}
內容的文件,-r
選項表示遞歸查找,-l
選項表示只顯示匹配到的文件,返回的結果多是多個的。sed -i '{ s/'"${original_class_name}"'/'"${result_class_name}"'/g }' `grep ${original_class_name} -rl ${pbxproj_dir}`
sed -i '{ s/'"${original_class_name}"'/'"${result_class_name}"'/g }' `grep ${original_class_name} -rl ${class_name_replace_dir}`
複製代碼
shell是面向過程的語言,不具有面向對象的特性,shell能夠把部分功能獨立分離出來,放在單獨的腳本文件中,其餘模塊能夠導入該腳本文件,使用其中的功能,這就是shell的僞面向對象
工具模塊是包含了工具方法的模塊,好比數學計算能夠放在一個單獨的文件中獨立爲一個模塊,其餘須要使用到的地方引入這個模塊,使用其中定義的方法便可
Math.sh
保存了一些數學計算函數
#!/bin/bash
power(){
base=$1
exp=$2
result=1
for (( i = 0; i < $exp; i++ )); do
result=$[ $result * $base ];
done
echo $result
}
複製代碼
其餘模塊使用. ./Math.sh
包含這個模塊,能夠調用其中定義的power方法
注意:. ./Math.sh
中.
是source
的簡寫,這裏也能夠寫成source ./Math.sh
echo "=======模塊======="
. ./Math.sh
result=$(power 3 5)
echo "3^5 = ${result}"
輸出:
=======模塊=======
3^5 = 243
複製代碼
流程模塊是包含了一些列操做的模塊,能夠向該模塊傳遞參數,也能夠有返回值。流程模塊中有兩個地方比較特別,一個是流程模塊自己參數的處理方式和外部調用流程模塊傳入參數的方式
流程模塊處理參數使用getopts
命令實現,getopts optionstring opt
其中optionstring
格式:i:o:
,i
和o
以後的:
表示指定i
選項和o
選項須要有參數,第一個:
表示忽略錯誤,使用case分支處理參數選項對應的參數值。
#### 參數解析
echo "參數>>${@}"
while getopts :i:o: opt
do
case "$opt" in
i) param_input_dir=$OPTARG
echo "Found the -i option, with parameter value $OPTARG"
;;
o) param_output_file=$OPTARG
echo "Found the -o option, with parameter value $OPTARG"
;;
*) echo "Unknown option: $opt";;
esac
done
echo "param_input_dir = ${param_input_dir}"
echo "param_output_file = ${param_output_file}"
複製代碼
參數的傳遞和使用命令行的選項相似,能夠在選項後面添加該選項的參數值
./GetAndStoreClasses.sh\
-i ${class_search_dir}\
-o ${cfg_file}
複製代碼
下面定義的是一個流程模塊的腳本文件,是injectContentShell#GetAndStoreClasses.sh
腳本文件中的代碼片斷,實現了生成重命名的類的配置腳本
功能,能夠傳遞兩個參數。
#!/bin/bash
########################
# 腳本功能:生成重命名的類的配置腳本
# 輸入參數 -i 輸入的文件夾
# 輸入參數 -o 保存的文件
########################
####### 參數定義
param_input_dir=""
param_output_file=""
####### 參數解析
echo "參數>>${@}"
while getopts :i:o: opt
do
case "$opt" in
i) param_input_dir=$OPTARG
echo "Found the -i option, with parameter value $OPTARG"
;;
o) param_output_file=$OPTARG
echo "Found the -o option, with parameter value $OPTARG"
;;
*) echo "Unknown option: $opt";;
esac
done
echo "param_input_dir = ${param_input_dir}"
echo "param_output_file = ${param_output_file}"
####### 配置
# 屬性黑名單配置文件
blacklist_cfg_file="$(pwd)/DefaultClassesBlackListConfig.cfg"
####### 數據定義
# 定義保存須要處理目標文件的數組
declare -a implement_source_file_array
declare -a implement_source_file_name_array
implement_source_file_count=0
# mark: p384
# 遞歸函數讀取目錄下的全部.m文件
function read_implement_file_recursively {
echo "read_implement_file_recursively"
if [[ -d $1 ]]; then
for item in $(ls $1); do
itemPath="$1/${item}"
if [[ -d $itemPath ]]; then
# 目錄
echo "處理目錄 ${itemPath}"
read_implement_file_recursively $itemPath
echo "處理目錄結束====="
else
# 文件
echo "處理文件 ${itemPath}"
if [[ $(expr "$item" : '.*\.m') -gt 0 ]]; then
echo ">>>>>>>>>>>>mmmmmmm"
implement_source_file_array[$implement_source_file_count]=${itemPath}
class_name=${item//".m"/""};
implement_source_file_name_array[$implement_source_file_count]=${class_name}
implement_source_file_count=$[ implement_source_file_count + 1 ];
fi
echo ""
fi
done
else
echo "err:不是一個目錄"
fi
}
post_implement_file_handle() {
local wirte_to_file=$1
# 寫入文件中
echo "# 須要處理的類配置文件" > ${wirte_to_file}
for(( i=0;i<${#implement_source_file_name_array[@]};i++))
do
class_file_name=${implement_source_file_name_array[i]};
echo ${class_file_name} >> ${wirte_to_file}
done;
# 去重
wirte_to_file_bak="${wirte_to_file}.bak"
mv ${wirte_to_file} ${wirte_to_file_bak}
sort ${wirte_to_file_bak} | uniq > ${wirte_to_file}
# 過濾
mv ${wirte_to_file} ${wirte_to_file_bak}
echo "# Properties Configs Filtered" > ${wirte_to_file}
IFS_OLD=$IFS
IFS=$'\n'
# 上一行的內容
lastLine="";
for line in $(cat ${wirte_to_file_bak} | sed 's/^[ \t]*//g')
do
grep_result=$(grep ${line} ${blacklist_cfg_file})
category_judge_substring="\+"
if [[ ${#line} -le 6 ]] || [[ $(expr "$line" : '^#.*') -gt 0 ]] || [[ -n ${grep_result} ]] || [[ ${line} =~ ${category_judge_substring} ]]; then
# 長度小於等於六、註釋內容的行、在黑名單中的內容、分類文件不處理
echo "less then 6 char line or comment line"
else
if [[ -n ${lastLine} ]]; then
# 上一行是非空白行
# 比較上一行內容是不是當前行的一部分,不是添加上一行
if [[ ${line} =~ ${lastLine} ]]; then
echo "${line} 和 ${lastLine} 有交集"
else
echo ${lastLine} >> ${wirte_to_file}
fi
fi
# 更新上一行
lastLine=${line}
fi
done
IFS=${IFS_OLD}
# 刪除臨時文件
rm -f ${wirte_to_file_bak}
}
read_implement_file_recursively ${param_input_dir}
post_implement_file_handle ${param_output_file}
複製代碼
在另外一個模塊中使用流程模塊
# 獲取須要重命名的類名稱,保存到配置文件中
./GetAndStoreClasses.sh\
-i ${class_search_dir}\
-o ${cfg_file}
複製代碼
下面是一個循環的輸入和檢測輸入是不是合法目錄的例子,是injectContentShell#FileUtil.sh
腳本文件中的代碼片斷
echo -n "請輸入目錄: "
是輸入的提示,-n
表示不換行,用戶的輸入跟隨在提示後面read path
把用戶的輸入內容保存在變量path中# 循環檢測輸入的文件夾
checkInputDestDirRecursive() {
echo -n "請輸入目錄: "
read path
if [[ -d $path ]]; then
CheckInputDestDirRecursiveReturnValue=$path
else
echo -n "輸入的目錄無效,"
checkInputDestDirRecursive
fi
}
複製代碼
在腳本中可能會有使用菜單選項進行交互的場景,有如下幾個要點
read -n 1 option
命令中用了-n選項來限制只讀取一個字符。這樣用戶只須要輸入一個數字,也不用按回車鍵,輸入的內容保存在option
變量中clear
命令是用來清空命令行的屏幕的echo -e
-e 選項用來處理轉義字符echo -en
-n 選項讓光標處於同一行,用戶的輸入會顯示在同一行while
循環獲取用戶的輸入,在while
循環中使用case
分支處理不一樣的操做如下腳本是injectContentShell#injectedContentShell.sh
文件中的一部分
function genMunu {
clear
echo
echo -e "\t\t\t選項菜單\n"
echo -e "\t1. 刪除注入內容"
echo -e "\t2. 添加註入內容"
echo -e "\t0. Exit menu\n\n"
echo -en "\t\tEnter option: "
read -n 1 option
}
while [[ 1 ]]; do
genMunu
case $option in
0 )
echo ""
echo "Bye"
exit 0
;;
1 )
# 刪除配置文件中注入的內容
removeInjectedContent
;;
2 )
# 添加配置文件中注入的內容
addInjectedContent
;;
h )
genMunu
;;
* )
echo "Wrong!!"
;;
esac
echo
echo -en "\n\n\tHit any key to continue"
read -n 1 line
done
複製代碼