shell script程式設計小結——附帶例項

WilsonLiu95發表於2019-02-16

shell script程式設計小結

前言

shell作為程式設計中不可或缺的一部分,平日裡,我們經常會在shell中輸入一些命令。有時候也需要完成一些複雜的操作,重複的輸入多條相同的命令,過於費時和無趣。所以掌握shell script就顯得非常有必要了,可以讓你用程式設計的方式呼叫繁多的命令列工具。

最近,正好碰上一個一直拖著的需求,便抄起了shell解決掉了,寫了人生中第一段shell script程式碼。

需求如下

從一個資料夾中獲取一個文字,這個文字里記錄了連結以及他對應的版本號。併到另外一個html資料夾中遍歷所有html檔案,將其中的連結中的@VERSION替換為相應的版本號。

流程

  1. 建立一個shell指令碼,例如touch test.sh

  2. 在命令列中輸入chmod +x ./test.sh,使這個檔案變成一個可執行檔案

  3. 在這個指令碼檔案中書寫程式碼,諸如”find .”

  4. 在命令列中輸入./test.sh,即可執行。

  5. 結果,輸出當前目錄下所有資料夾與檔案的名稱

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檔案。

github專案地址

配置函式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

相關文章