2015/03/18

bash 字串切割

設定值的內容使用某個字符區隔各單項內容是很常見的,如何在 script 將這些內容切割出來使用是很重要的課題,需要使用到的是內建的 $IFS 這個變數。嘗試執行下面的 script 可以很容易理解 $IFS 的運作。
#!/bin/sh
set - $(IFS=" "; echo This is a book)
echo $1
echo $2
echo $3
echo $4

得到的結果是 $1="This", $2="is", $3="a", $4="book",所以 set - $(IFS=" "; echo This is a book) 就是把後面的字串用空白字元 " " 當作區隔,把切割後的內容放到 $1, $2...。
以下的範例是利用 $IFS 來尋找執行檔存在哪個 $PATH 資料夾內,我習慣取名為 findpath
if [ 1 -eq $# ]; then
    RESULT="not found!"
    FILENAME=$1
    set - $(IFS=":"; echo $PATH)
    i=1
    eval "DIR=\$$i"
    until [ "" == "$DIR" ]
    do
        if [ -x "$DIR/$FILENAME" ]; then
            RESULT="$DIR/$FILENAME"
            DIR=""
        else
            i=$(($i+1))
            eval "DIR=\$$i"
        fi
    done
    echo $RESULT
else
    echo "Syntax: $0 [filename]"
    echo "    filename: The filenam you want to find in PATH"
fi

應用在 for 迴圈

findpath 的另一個寫法,先把原本的 IFS 存到 IFS_SAVE,然後指定冒號 ":" 為切割符號,這時候 for DIR in $PATH 就會把 $PATH 用冒號將每個單位切出來使用。
if [ 1 -eq $# ]; then
    RESULT="not found!"
    IFS_SAVE="$IFS"
    IFS=":"
    for DIR in $PATH
    do
        if [ -x "$DIR/$1" ]; then
            RESULT="$DIR/$1"
            break
        fi
    done
    IFS="$IFS_SAVE"
    echo $RESULT
else
    echo "Syntax: $0 [filename]"
    echo "    filename: The filenam you want to find in PATH"
fi

IFS 的初始值

執行 set | grep IFS 可以看到目前的 IFS 設定值,在還沒變更之前就是初始值,一般是
IFS=$' \t\n'

沒有留言: