開發時難免都會需要撰寫 shell script 將一些瑣碎的事情自動化,最常見的大概就是利用 bash 撰寫 shell script 。

不過 bash 有些功能並非為眾人皆知卻十分方便,例如 shell parameter expansion 就有許多好用的功能,例如算字串長度、字串取代、大小寫轉換等等,如果學會運用,可以事半功倍!

本篇將介紹幾種好用的 shell parameter expansion 。

本文環境

  • Bash 5.0
  • macOS 10.15

前言

在 bash 中, ${parameter} 的寫法是 parameter expansion 的基本形式,代表取得 parameter 的值,例如以下 bash script 即是透過 ${VAR} 的方式取得 VAR 的值,所以可以印出 HelloWorld :

#!/bin/bash
VAR="HelloWorld"

echo ${VAR}

p.s. ${VAR} 其實可以省略為 $VAR ,也就是我們很常見的 bash script 變數用法。

除了透過基本形式取得變數值的部分, parameter expansion 還提供在 parameter 前方或後方加上一些特殊符號,例如 # / @ …. 等等以擴充其用途,例如取得字串長度,字串取代、對變數進行賦值等等。

字串長度

首先看利用 shell parameter expansion 取得字串長度的方法。

十分簡單,只要在 parameter 的前方加上 # 即可,例如以下範例:

$ string=abcdefghi
$ echo ${#string}
9

字串切片

bash 的 shell parameter expansion 也有類似 Python slice 切片的功能,例如 ${string:2} 取得字串第 2 個字元之後的所有字元,以及 ${string:2} 取的字串第 2 個字元之後 1 個字元:

$ string=abcdefghi
$ echo ${string:2}
cdefghj
$ echo ${string:2:1}
c

字串刪除

bash 的 parameter expansion 也有提供若干字串刪除的方式,包含刪除字串的前綴(prefix)、字串的後綴(postfix)、刪除符合的字串等。

刪除字串前綴(prefix)

如果想刪除某些字串前面固定格式的字元時,可以在 parameter 後方加上 # 以及欲刪除的前綴(prefix),例如以下範例想刪除字串開頭的 abc (如果 parameter 不是 abc 開頭則不會進行任何動作喔):

$ string=abcdefghi
$ echo ${string#abc}
defghi

刪除後綴(postfix)字串

如果想刪除某些字串後面固定格式的字元時,則可以在 parameter 後方加上 % 以及欲刪除的後綴(prefix),例如以下範例想刪除字串結尾的 ghi (如果 parameter 不是 ghi 結尾則不會進行任何動作喔):

$ string=abcdefghi
$ echo ${string%ghi}
abcdef

刪除符合的字串

如果沒辦法知道想刪除的字串會在哪個位置出現,則可以在 parameter 後方使用 / 加上欲刪除的字串,例如以下範例刪除字串中間的 def :

$ string=abcdefghi
$ echo ${string/def}
abcghi

取代字串

取代字串的方式與刪除類似,額外加上 /取代字串 即可,例如以下範例將 def 取代為 3 個米字號:

$ string=abcdefghi
$ echo ${string/def/***}
abc***ghi

如果取代的字串出現多次,上述的寫法僅會取代 1 次,例如:

$ string=abcabcabc
$ echo ${string/abc/***}
***abcabc

如果要取代多次出現的字串,可以將 / 改為 // 例如以下 //abc/*** 的部分:

$ string=abcabcabc
$ echo ${string//abc/***}
*********

字串轉換大小寫

bash 的 parameter expansion 也提供大小寫轉換的功能,而且也十分好記:

  • ^ 代表第 1 個字元轉大寫
  • ^^ 代表全部轉大寫
  • , 代表第 1 個字元轉小寫
  • ,, 代表全部轉小寫

詳見以下範例:

字串轉大寫

$ string=abcdefghi
$ echo ${string^}
Abcdefghi
$ echo ${string^^}
ABCDEFGHI

字串轉小寫

$ string=ABCDEFGHI
$ echo ${string,}
aBCDEFGHI
$ echo ${string,,}
abcdefghi

取得檔名與副檔名

結合前述提到的各種字串處理的技巧,我們就能更方便地做到一些事,例如經常會用到的取得檔名與副檔名:

$ file=filename.txt
$ echo ${file%.*}
filename
$ echo ${file#*.}
txt

上述 ${file%.*} 中的 %.* 指的是刪除 . 之後(包含 . )的所有字元。

${file#*.} 中的 #.* 指的則是刪除 . 之前(包含 . )的所有字元。

結語

Bash 的 shell parameter expansion 文件中,還有許多其他方便的用法,有興趣的話,可以花時間實際閱讀與操作看看,相信能夠收穫不少。

以上, Happy Coding!

References

https://www.linuxjournal.com/content/bash-parameter-expansion

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html