---
# System prepended metadata

title: shell script模板
tags: [shell, template]

---

# shell script模板
```shell
#!/bin/bash

########## 基礎腳本
script_name="$(basename "$(realpath "${BASH_SOURCE[0]}")")"
script_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
export -n script_name
export -n script_dir
export -n scriptStartTime

########## DEBUG函數
scriptDebugFile="$scriptDir/${scriptName}.debug"
export -n scriptDebugFile
truncate -s 0 "$scriptDebugFile"

if ! declare -F logExec > /dev/null; then
logExec()
{
  cmdStr=()
  local backNLine=0

  # 如果上上行是 "\" 結尾的，推入 cmdStr
  while [[ "$(awk "NR==$1-$backNLine {print prev} {prev=\$0}" "$scriptDir/$scriptName")" == *"\\" ]]; do
    cmdStr+=("$(awk "NR==$1-$backNLine+1 {print prev} {prev=\$0}" "$scriptDir/$scriptName")")
    backNLine=$(($backNLine+1))
  done
  
  # 輸出最後一行 去除頭部空格
  evalStr="$(basename "$scriptDir")/$scriptName:$1 $(awk "NR==$1-$backNLine+1 {print prev} {prev=\$0}" "$scriptDir/$scriptName")"
  output="$(printf '%s' "$evalStr" | sed 's/^[ \t]*//')"
  color yellow "$output"

  # 吐出 cmdStr
  while [[ ${#cmdStr[@]} -ne 0 ]]; do
    evalStr="$(basename $scriptDir)/$scriptName:$1 ${cmdStr[-1]}"
    output="$(printf '%s' "$evalStr" | sed 's/^[ \t]*//')"
    color yellow "$output"
    unset cmdStr[-1]
  done

 }
fi

if ! declare -F retChk > /dev/null; then
retChk()
{
  if [[ $? -eq 0 ]]; then
    #color green "SUC" | sudo tee -a "$scriptDebugFile" > /dev/null
    color green "SUC"
  else
    #color red "FAIL" | sudo tee -a "$scriptDebugFile" > /dev/null
    color red "FAIL"
    #tail -3 "$scriptDebugFile"
  fi
  return $1
}
fi

if ! declare -F retChkExit > /dev/null; then
retChkExit()
{
  if [[ $? -eq 0 ]]; then
    #color green "SUC" | sudo tee -a "$scriptDebugFile" > /dev/null
    color green "SUC"
  else
    #color red "FAIL" | sudo tee -a "$scriptDebugFile" > /dev/null
    color red "FAIL"
    #tail -3 "$scriptDebugFile"
    exit 1
  fi
  return $1
}
fi

########## 選項設定
ARGS=$(getopt -o \
hv\
\
\
 --long \
help,version,\
\
 -n $(basename "$0") -- "$@")

eval set -- "$ARGS"

while true; do
  case "$1" in
    -h | --help)
      showHelp
      exit 0
      ;;
    --)
      shift
      break
      ;;
    *)
      echo "Internal error!" >&2
      exit 1
      ;;
	esac
done

source $scriptDir/color.sh

# 相對目錄修正為腳本位置，任何source請在此之前完成，以避免任何相對路徑問題。
cd $scriptDir

set -T # 讓 DEBUG trap 在函數中作用

trap '[[ "${FUNCNAME[0]}" != *"retChk"* && "${FUNCNAME[0]}" != "logExec"* && "${FUNCNAME[0]}" != "color"* && "$BASH_COMMAND" != *"retChk"* ]] && logExec $LINENO' DEBUG

```


# 說明
```
# arguments setting
ARGS=$(getopt -o \
hv\
\
\
 --long \
help,version,\
\
\
 -n $(basename "$0") -- "$@")
```
`-n`: 錯誤信息的前綴，通常為`$0`
`--`: 命令行參數分隔運算符，此運算符後的東西全是參數，不是選項。此處傳入 `$@(所有選項)`。
短選項
第二個`\`: `X`
第三個`\`: `X:`
第四個`\`: `X::`
長選項
第六個`\`:`XX`，六七八使用`,`分隔。
第七個`\`: `XX:`
第八個`\`: `XX::`

`eval set -- "$ARGS"`: 這會重新設置文件的參數，此處設定無選項(`--`之後都是參數)，把`$ARGS`全當參數。
`shift`: 這會把 `$2`往左變成`$1`，不會改變`$0`，丟棄`$1`。
然後下一段會不斷吃`$1`，然後`shift`，直到吃到了`--`，代表之後都是真正的參數，shift掉`--`後停止吃參數。此時的`$1`就是理想的真參數，不是選項了。

### 選項說明
`X`和`XX`:
無參數。

`X:`:必有參
空格或貼著

`X::`:可選參
只能貼著

`XX:`:必有參
空格或`=`

`XX::`:可選參
只能`=`

總結:
短選項，不可 `=`，`=`會變成參數的一部分，相等於貼著。最好貼著。
長選項，不可貼著，否則變成別的參數。最好用`=`。
只有必有參可用空格。

# 輸出有顏色的字
```
在 Shell 腳本中輸出有顏色的字，通常是通過 ANSI escape codes 來實現的。這些 escape codes 讓你可以控制文字的顏色、背景顏色、字型等。最常見的做法是使用 echo 或 printf 命令來顯示彩色文字。
基本語法

ANSI escape codes 的基本語法如下：

echo -e "\033[<color_code>m<text>\033[0m"

    \033 是轉義字符，表示你要開始進行顏色設定。
    [<color_code>m 會設置顏色，<color_code> 是顏色代碼。
    \033[0m 會重置顏色，讓後續的文字恢復為預設顏色。

顏色代碼

顏色代碼通常有兩種類型：前景顏色（文字顏色）和背景顏色。常見的顏色代碼如下：
顏色	前景顏色代碼	背景顏色代碼
黑色	30	40
紅色	31	41
綠色	32	42
黃色	33	43
藍色	34	44
紫色	35	45
青色	36	46
白色	37	47
預設顏色	39	49

此外，還有一些字型效果，如加粗（1）、下劃線（4）等。
範例：輸出不同顏色的文字
1. 紅色文字

echo -e "\033[31mThis is red text\033[0m"

2. 綠色文字

echo -e "\033[32mThis is green text\033[0m"

3. 藍色文字，背景黃色

echo -e "\033[34;43mThis is blue text on yellow background\033[0m"

4. 加粗紅色文字

echo -e "\033[1;31mThis is bold red text\033[0m"

5. 文字加下劃線

echo -e "\033[4;32mThis is underlined green text\033[0m"

結合顏色和背景顏色

你可以將前景顏色和背景顏色結合在一起：

echo -e "\033[31;47mRed text on white background\033[0m"

    31 代表紅色（前景顏色）。
    47 代表白色（背景顏色）。

使用 printf（較為推薦的方式）

printf 在處理顏色輸出時比 echo 更為靈活，它不會自動處理特殊字符，因此更適合輸出包含轉義序列的內容。

printf "\033[32mThis is green text\033[0m\n"

定義顏色的函數

為了提高腳本的可讀性，可以將顏色輸出封裝成函數。例如：

# 定義顏色函數
color_red() {
    echo -e "\033[31m$1\033[0m"
}

color_green() {
    echo -e "\033[32m$1\033[0m"
}

# 使用顏色函數
color_red "This is red text"
color_green "This is green text"

這樣，你可以在腳本中方便地重複使用顏色輸出的功能。
顏色參數化函數（更通用的方式）

你也可以寫一個更通用的函數來接收顏色參數，這樣可以靈活控制顏色：

color_text() {
    local color=$1
    local text=$2
    echo -e "\033[${color}m${text}\033[0m"
}

# 使用範例
color_text "31" "This is red text"
color_text "32" "This is green text"
color_text "34;43" "This is blue text on yellow background"

完整的顏色參數例子

color_text "1;33" "This is bold yellow text"
color_text "4;36" "This is underlined cyan text"

小結

這些 ANSI escape codes 讓你在腳本中輸出有顏色的文字非常簡單。你可以根據需要選擇使用 echo 或 printf，並可以自定義顏色參數以達到更多的顯示效果。
```


https://gmplib.org/download/gmp/gmp-6.2.1.tar.xz

# xxx=""

MFText="\
family(\"Compiler\")
prepend_path (\"MODULEPATH\", pathJoin (mfroot, \"Compiler\", package)) \\
prepend_path (\"MODULEPATH\", pathJoin (mfroot, \"MPI\", package)) \\
"

`\` 代表不換行
```
x="
...


"
```
代表換行