2010年2月23日

[Shell Script] 如何擷取字串中的子字串

今天要分享的是,在 shell script 中擷取子字串 (俗稱 substring) 的技巧 (各程式語言都要提供的最基本功能)。

一開始在學 shell script 的時候,我看的是臥龍小三的網站 (News 裡面的 Shell 入門),按照順序看過一遍固然收穫很多,但也僅止於「快速入門」的程度,也就是「讓你不要害怕 shell script」的作用,其中對字串處理這種重要的功能並沒有整理的很詳細,因此我一開始連「取出某個字串的最後一個字元」這樣的功能都不知道如何下手,用 sedawk 都不太對。後來透過孤狗大神找到了幾種方法:

法一:Bash Shell Programming in Linux (搜尋 substring)

time=”20:06:16”
unit=${time:${#time}-1:${#time}} –> $time變數要寫三次!
這個寫法顯然相當之囉嗦,但是它是有效的。

法二:parsing a string in a shell script (透過 awk 來做)

time=”20:06:16”
unit=`echo $time | awk '{print substr($0, length($0), length($0))}'` –> 可用 $0 取代 $time,較簡潔


但整體看來還是非常囉嗦,我只是要取出一個字串的最後一個字元而已阿!

法三:臥龍小三-Linux Shell 程式設計實務 (Chapter 08: 8-4 使用外部程式 expr 做算數運算)

time=”20:06:16”
startPos=$(expr length $time)
unit=`expr substr $time $startPos 1` -> 注意 $time 要被包在“ “裡面


這章介紹的 expr 功能還蠻多的,有找子字串 index 和做 substring 等等功能,值得練習一下。這個作法雖然少了很多小括號,但感覺還是挺麻煩的,最後,終於讓我找到一個最簡單直覺的作法:

法四:一樣出自 parsing a string in a shell script (看這個留言)

time=”20:06:16”
unit=`echo $time | tail -c 2
–> 重點在 -c 這個參數,以及用 tail 的話 byte 數要多 +1 (取最後1個字元:2)

tail-c

一行搞定!而且非常的直覺!除了要取出特定字串以外,如果是要正取 (用 head)或倒取 (用 tail) 固定幾個字元的話,應該都會用 head/tail 來做吧!

以上就是今天的分享,如有更好的作法還請不吝賜教 ^^~

PS. 取出字串的最後一個字元,在 Perl 中也非常簡單:substr $time, -1,負號代表由字尾開始往前面取

3 則留言:

ctbstrong 提到...

我同事提供一個更簡潔的方式,不用呼叫其他的程式

time="20:06:16"
unit=`expr $time : '.*\(.\)'`

如果字串後面有空白,像是 time="20:16:16 ",還會自動 trim 掉。要取其他位置的數值,也可自行調整 regular expression 的部份。

Unknown 提到...

感謝 ctbstrong 提供的作法,經過測試的確可行,又多學到一招 :)

Unknown 提到...

最近剛好學到這邊

關於法一
time="20:06:16"
unit=${time:${#time}-1}
應該就可以了


另外:
time="20:06:16"
unit=${time#${time%?}}

Google Spreadsheet 裡用規則運算式

最近因為工作關係,遇到要用 Google Form 及 Google Sheet 所以研究了 Google Sheet 裡的一些 function 怎麼用 首先,分享一下如何在 Google Sheet 裡用規則運算 :D