作者:aron1992
來源:https://my.oschina.net/FEEDFACF/blog/1789695
0. 背景
之前寫了系列的shell實戰的文章,得到了挺多小夥伴的關註,遇到有些對shell不太熟悉小夥伴,所以有個想法寫一篇shell入門的文章。
時間流逝,再回頭去看看過去的東西,才會發現哪些東西比較重要,故撰此文,記錄我在過去學習和使用shell語言過程中我個人覺得比較重要的部分,做一個小總結和分享。
文章中使用到的程式碼位置:https://gitee.com/dhar/YTTInjectedContentKit/tree/master/DevPods/InjectedContentKit/Example/injectContentShell
和
https://gitee.com/dhar/ShellLearning/tree/master/helloshell
文章內容結構如下:
-
語法
-
變數
-
列印
-
運算
-
控制
-
迴圈
-
容器
-
方法
-
檔案
-
檔案讀取
-
檔案寫入
-
sed流編輯
-
模組
-
工具模組
-
流程模組
-
輸入和選單
-
獲取輸入
-
選單
1. 語法
1.1 變數
變數的定義
定義一個變數和其他語言的類似,shell是弱型別語言所以不需要使用型別限定,並且變數可以修改型別,下麵的例子定義了一個字串型別的str變數,之後修改為數值型別
註意點:變數等號兩邊不能有空格出現
str="string"echo $strecho ${str}str=123echo $str
變數使用
變數可以賦值給另一個變數和列印,當變數被使用的時候需要在變數名稱前面加上$符號,還有另一種方式是把變數名放在${}括號中使用,可以把命令執行結果作為右值賦值給變數
str2=$strecho $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
1.2 列印
因為shell沒有單步除錯和其他功能強大的IDE,所以列印功能就經常使用到,此外列印功能還可以當做函式的傳回值,比return作為函式的傳回值功能更強大,shell 使用echo列印,內容預設輸出到控制臺中,echo可以列印字串、變數、以及字串中嵌入變數的混個內容,echo有幾重要的引數選項
-
-e 跳脫字元處理,比如\t顯示為製表符而不是顯示輸出\t
-
-n 把文字字串和命令輸出顯示在同一行中
str4="string4"echo $str4echo "str4=$str4"echo "str4=${str4}str3=${str3}"# 輸出:=======列印=======
string4
str4=string4
str4=string4str3=123
1.3 運算
使用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
1.4 控制
數值比較
控制使用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"fiif [[ -z $str1 ]]; then
echo "str1 為空"else
echo "str1 不為空"fistr1=""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} 檔案不存在"fiif [[ -f $file ]]; then
echo "${file} 是一個檔案"else
echo "${file} 不是一個檔案"fiif [[ -d $file ]]; then
echo "${file} 是一個檔案夾"else
echo "${file} 不是一個檔案夾"fi# 輸出:=======控制檔案比較=======
syntax.sh 檔案存在
syntax.sh 是一個檔案
syntax.sh 不是一個檔案夾
1.5 迴圈
C語言格式的for迴圈
echo "=======迴圈for======="num=0for (( i = 0; i < 10; i++ )); do
num=$[$num + $i]doneecho "result = ${num}"# 輸出:=======迴圈for=======
result = 45
for in 迴圈處理檔案
data檔案內容如下:
➜ helloshell git:(master) ✗ cat dataThe 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=$IFSIFS=$'\n'for line in $(cat $file)do
echo "${line}"doneIFS=${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 迴圈
while表示條件滿足執行迴圈,比如下麵的例子是9*9乘法口訣表中的一部分,表示i從1迴圈到9
i=1while [[ i -lt 10 ]]; do
i=$(expr $i + 1)
done
until 迴圈
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}
1.6 容器
陣列的定義如下 declare -a array_name
註意:osx系統因為bash的版本太低,只能定義索引陣列,在bash版本高於4.1的版本可以使用declare -A array_name定義關聯陣列
以下的程式碼片定義一個陣列,用於儲存配置檔案中的內容,然後使用for迴圈遍歷陣列內容輸出到控制檯。
-
config_content_array[$cfg_line_count]=$line 把內容儲存到陣列
-
${#config_content_array[@]} 獲取陣列的元素個數
-
config_content=${config_content_array[i]}; 讀取陣列第i個元素
####### 資料定義# 定義儲存類名稱的陣列declare -a config_content_array
cfg_line_count=0# 1、讀取配置檔案內容儲存到陣列中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}
1.7 方法
方法的定義有兩種方式
-
function func1 { #這裡定義方法體 }
-
func2() { #這裡定義方法體 }
方法傳回值的處理有三種方式
-
return 最大傳回256,表示結果碼,有特殊含義,並且只能傳回數值
-
echo 傳回
-
儲存在全域性變數中
方法的引數
-
引數的傳遞新增在方法之後,多個使用空格分割
-
引數的獲取使用$1,$2以此類推,特別地$0表示檔案名、$#表示引數的個數
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 invokedreturn 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
2. 檔案
2.1 檔案讀取
檔案的讀取可以使用cat命令結合for in迴圈處理
註意:$IFS是檔案迴圈處理的分隔符,按按行處理資料需要把該值設定為$’\n’,處理完成之後恢複舊值
echo "=======檔案======="file="data"IFS_OLD=$IFSIFS=$'\n'for line in $(cat $file)do
echo "${line}"doneIFS=${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.
2.2 目錄的讀取
檔案的讀取可以使用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
2.3 檔案寫入
使用輸出重定向把內容輸出到檔案
-
>輸出重定向符號先清空檔案然後把內容寫入到檔案中
-
>>輸出重定向符號把內容追加寫入到檔案中
此外可以結合其他命令實現排序、去重功能
-
sort命令對檔案內容以行作為單位排序
-
uniq命令對檔案內容進行去重,以行為單位,一般需要結合sort命令使用
file="subfolder/data2"destfile="subfolder/data2-p"sort ${file} | uniq > ${destfile}
結果:
➜ helloshell git:(master) ✗ cat subfolder/data2The 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 brownThe quick brown fox jumps over the lazy dog.
fox
jumps over the lazy dog.
3. Sed流編輯
Sed流編輯結合正則運算式可以方便的對文字檔案進行查詢、修改、刪除、增加等操作
註意:osx系統自帶的sed命令和標準的gnu-sed使用方式上有些差別,所以以下篇幅所談論到的sed都是標準的gnu-sed,下麵的這個指令碼用於判斷系統是否安裝了gnu-sed,如果沒有會自動進行安裝,完成之後需要使用者執行顯示的命令配置下即可。
# 檢測是否安裝gnu sed,mac 內建的sed會有些問題,所以需要安裝gnu sedgnuSedInstallCheck() { # 檢查是否安裝gnused
# mac安裝gnuSed 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 "檢測到使用gnu 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 gnu sed...'
brew install gnu-sed --with-default-names || exit 1 # 設定區域性環境變數
echo "set PATH...."
source ./set-gnu-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
sed param
-
-e script 在處理輸入時,將script中指定的命令新增到已有的命令中
-
-f file 在處理輸入時,將file中指定的命令新增到已有的命令中
-
-n 不產生命令輸出,使用print命令來完成輸出
-
-i 把修改寫入到原檔案中
sed operation
-
s 替換
-
a 追加
-
d 刪除
sed pattern/replacement
查詢對應的樣式和匹配樣式的替換內容
sed flag
有4種可用的替換標記:
-
數字,表明新文字將替換第幾處樣式匹配的地方;
-
g,表明新文字將會替換所有匹配的文字;
-
p,表明原先行的內容要打印出來;
-
w file,將替換的結果寫到檔案中。
3.1 sed新增內容
以下是injectContentShell#injectedContentShell.sh指令碼檔案中的程式碼片段,使用a操作吧內容新增到方法的開頭
-
/^- \(.*\){$/這部分是pattern,匹配OC中方法的開始
-
a\ ‘”$injected_content”‘這部分是operation,註意其中插入內容的變數要使用雙引號和單引號包含處理
# 在匹配的行下麵新增插入內容sed -i '/^- \(.*\){$/{
a\ '"$injected_content"'
}' ${file}
3.2 sed刪除內容
以下是injectContentShell#injectedContentShell.sh指令碼檔案中的程式碼片段,使用d操作刪除內容
sed -i '/'"$pattern_str"'/ {
d
}' ${file}
3.3 sed修改替換內容
以下是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}`
4. 模組
shell是面向過程的語言,不具備面向物件的特性,shell可以把部分功能獨立分離出來,放在單獨的指令碼檔案中,其他模組可以匯入該指令碼檔案,使用其中的功能,這就是shell的偽面向物件
4.1 工具模組
工具模組是包含了工具方法的模組,比如數學計算可以放在一個單獨的檔案中獨立為一個模組,其他需要使用到的地方引入這個模組,使用其中定義的方法即可
Math.sh儲存了一些數學計算函式
#!/bin/bashpower(){
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
4.2 流程模組
流程模組是包含了一些列操作的模組,可以向該模組傳遞引數,也可以有傳回值。流程模組中有兩個地方比較特別,一個是流程模組本身引數的處理方式和外部呼叫流程模組傳入引數的方式
流程模組處理引數
流程模組處理引數使用getopts命令實現,getopts optionstring opt其中optionstring格式:i:o:,i和o之後的:表示指定i選項和o選項需要有引數,第一個:表示忽略錯誤,使用case分支處理引數選項對應的引數值。
#### 引數解析echo "引數>>${@}"while getopts :i:o: optdo
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";; esacdoneecho "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: optdo
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";; esacdoneecho "param_input_dir = ${param_input_dir}"echo "param_output_file = ${param_output_file}"####### 配置# 屬性黑名單配置檔案blacklist_cfg_file="$(pwd)/DefaultClassesBlackListConfig.cfg"####### 資料定義# 定義儲存需要處理標的檔案的陣列declare -a implement_source_file_arraydeclare -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
# 長度小於等於6、註釋內容的行、在黑名單中的內容、分類檔案不處理
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}
5. 輸入和選單
5.1 獲取輸入
下麵是一個迴圈的輸入和檢測輸入是否是合法目錄的例子,是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}
5.2 選單
在指令碼中可能會有使用選單選項進行互動的場景,有以下幾個要點
-
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 linedone
《Linux雲端計算及運維架構師高薪實戰班》2018年05月14日即將開課中,120天衝擊Linux運維年薪30萬,改變速約~~~~
*宣告:推送內容及圖片來源於網路,部分內容會有所改動,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。
– END –
更多Linux好文請點選【閱讀原文】哦
↓↓↓