shell script程式設計小結
前言
shell作為程式設計中不可或缺的一部分,平日裡,我們經常會在shell中輸入一些命令。有時候也需要完成一些複雜的操作,重複的輸入多條相同的命令,過於費時和無趣。所以掌握shell script就顯得非常有必要了,可以讓你用程式設計的方式呼叫繁多的命令列工具。
最近,正好碰上一個一直拖著的需求,便抄起了shell解決掉了,寫了人生中第一段shell script程式碼。
需求如下
從一個資料夾中獲取一個文字,這個文字里記錄了連結以及他對應的版本號。併到另外一個html資料夾中遍歷所有html檔案,將其中的連結中的@VERSION替換為相應的版本號。
流程
-
建立一個shell指令碼,例如
touch test.sh
-
在命令列中輸入
chmod +x ./test.sh
,使這個檔案變成一個可執行檔案 -
在這個指令碼檔案中書寫程式碼,諸如”find .”
-
在命令列中輸入
./test.sh
,即可執行。 -
結果,輸出當前目錄下所有資料夾與檔案的名稱
shell script介紹
和所有的程式設計一樣,shell指令碼主要由自身語法,以及繁多的linux命令構成。我們只需要學習shell指令碼自身的語法以及一些常用的linux命令即可,需要的時候可以查詢相應的linux命令。
shell script語法
因為篇幅限制,所以僅列出提綱,具體的學習可以參考文末的參考資料
-
變數
-
陣列
-
傳參
-
運算子
-
輸入輸出以及重定向
-
測試 test
-
流程控制
-
函式
-
檔案包含
linux命令
linux命令是linux強大的一個重要基礎,分為以下5個部分。程式設計中,用對了指令可以減少許多工作。也正因為繁多的指令,給shell指令碼帶來了足夠的能力。
-
系統管理
-
網路管理
-
軟體 | 列印 | 開發 | 工具
-
檔案目錄管理
-
硬體 | 監測 | 核心 | Shell
例項講解
程式碼分為三個函式,第一個配置初始化函式init()
,第二個遍歷資料夾函式walk()
,第三個是對html檔案的處理函式,運用sed正則替換html中的連結html_into_ver()
想要實際操作的可以拿這個kindle文字伴侶進行測試,這個專案是用去哪兒的前端構建工具fekit構建的。指令碼名字為export_html
,可以在命令列中輸入./export_html
進行測試,會多出一個export_html
的資料夾,裡面存放著所有的輸出html檔案。
配置函式init()
這一部分主要是預設配置的設定
function init()
{
# html_into_ver配置區
de_reg_rule="(.*)(http://localhost/kindleClipingDeal/prd/)(.*)(@VERSION)(.*)".*"
de_cur_prefix="http://localhost/kindleClipingDeal" #當前prd前面的路徑
de_replace_prefix="http://wilsonliu.cn/kindleClipingDeal" #當前字首替換後路徑
de_ver_file="ver/versions.mapping" #當前儲存版本號碼的檔案
de_target_dir="export_html" #將html修改後,輸出的目標資料夾
de_source_dir="html" # 原始檔夾為html
# 如果目標資料夾存在,則先刪除
if [ -e ${de_target_dir} ]; then
rm -rf ${de_target_dir}
fi
#首先複製原始檔夾為輸出資料夾,在輸出資料夾
cp -rf ${de_source_dir} ${de_target_dir}
# walk 的3個引數配置
de_dir_to_walk=${de_target_dir} #將要遍歷操作資料夾
de_walk_file_callback="html_into_ver" #檔案處理回撥函式
de_walk_dir_callback="" #資料夾處理回撥函式,非必要,可為空
# 呼叫walk函式
walk $de_dir_to_walk $de_walk_file_callback $de_walk_dir_callback
}
init; # 程式初始化執行
遍歷資料夾函式walk()
<!-- #!/bin/bash -->
# walk 函式 三個配置
# 第一個是遍歷的目標檔案,第二個是對檔案處理的呼叫函式,第三個是對資料夾處理的呼叫函式,
# 呼叫函式 有兩個輸入一個是遍歷的資料夾,一個是當前資料夾
function walk()
{
# ${1}為呼叫walk函式時傳入的第一個引數
for file in `ls ${1}` #ls輸出當前路徑下的所有檔案以及資料夾,利用for in分別對其進行操作
do
path=${1}"/"${file} #拼接當前將要處理的檔案或資料夾路徑
if [ -d ${path} ] #-d 是測試其是否是資料夾
then
# 如果存在回撥函式,則呼叫檔案處理回撥函式 並且輸入遍歷的目標資料夾以及當前資料夾路徑
if [ ${3} ] # ${3} 即為呼叫walk時輸入的第三個引數,應該為資料夾處理函式
then
$3 $1 ${path} #呼叫${3}指向的函式,並傳入當前所在路徑以及要處理的資料夾路徑
fi
# 對當前資料夾繼續呼叫walk函式
walk ${path} $2 $3 #遍歷資料夾
else
# 呼叫檔案處理函式對檔案進行處理,並輸入遍歷的目標資料夾以及當前檔案路徑
$2 $1 ${path}
fi
done
}
html檔案處理函式html_into_ver()
利用sed流編輯器進行正則匹配與替換
# 將html中的所有連結中的 VERSION 改為正確的版本號碼
function html_into_ver()
{
# 獲取當前$2的html檔案內所有的連結地址
link=`sed -n "s#${de_reg_rule}#2345#p" $2`
# 獲取當前$2的html檔案內所有的連線路徑
link_path=`sed -n "s#${de_reg_rule}#35#p" $2`
i=1
while [ `echo ${link} | cut -d " " -f $i` ]; do
cur_link=`echo ${link} | cut -d " " -f $i` #html中的完整路徑
cur_link_path=`echo ${link_path} | cut -d " " -f $i` #html中的完整路徑
cur_version=`sed -n "s*${cur_link_path}#**p" ${de_ver_file}` #當前檔案的版本號
cur_replace_link=`echo ${cur_link} | sed -n "s#(.*)(@VERSION)(.*)#1@${cur_version}3#p"` #當前替代cur_link的連結
#因為sed -i這個命令在mac與linux上存在差異,mac上強制要求sed -i 後多一個引數用來指替備份檔名,可以用空字元來解決,mac上輸出為Darwin,依次判斷
if [ `uname -s` == "Darwin" ]; then
sed -i "" "s#${cur_link}#${cur_replace_link}#" ${2} #直接對當前檔案進行VERSION修改
else
sed -i "s#${cur_link}#${cur_replace_link}#" ${2} #直接對當前檔案進行VERSION修改
fi
# 迴圈的條件
i=`expr $i + 1`
done
#統一修改連結字首
if [ `uname -s` == "Darwin" ]; then
sed -i "" "s#${de_cur_prefix}#${de_replace_prefix}#g" ${2} #修改連結的前置部分
else
sed -i "s#${de_cur_prefix}#${de_replace_prefix}#g" ${2} #修改連結的前置部分
fi
}
寫在最後
shell程式設計的好處在於可以批量化自動化操作以提高開發效率,同時也可以用來解決許多問題,本身並不複雜,簡單易學,功能強大。
希望大家都能夠掌握這一工具。
參考資料
WilsonLiu`s blog首發地址:http://blog.wilsonliu.cn