ziguzagu.org

シェルスクリプトの変数展開(評価)でパターンマッチ

zsh で、変数の展開(評価)にパターンマッチ(正規表現じゃないの)が使えるっていうのを知った。zsh でしか試してないけど、他の shell でもできたりするのかも。

パターンマッチで削除系

${name#pattern}
${name##pattern}

pattern が変数 $name の先頭にマッチしたら、マッチした部分を除いた値に置換。# が最短マッチで、## が最長マッチ。

${name%pattern}
${name%%pattern}

前述の # のマッチの逆で、末尾にマッチ。% が最短マッチで、%% が最長マッチってのも同じ風。

${name:#pattern}

pattern が変数 $name にマッチしたら空文字列を返す。

パターンマッチで置換系

${name/pattern/repl} ${name//pattern/repl}

変数 $name の pattern にマッチする部分を repl に置換。 name の後の / が1個のやつは、最初にマッチしたものだけ置換、/ が2個になるとマッチしたもの全部置換。perl/sed とかの正規表現の g オプションとおなじ。

とか。うーん、そうかー。代入系の評価式(:= とか :+ とか)だけじゃないんだなー。まぁ、全部 sed でできるんだけども。。

そもそもやりたかったこと

コマンドライン引数の最後をのぞく引数全部を簡単にとりたい、ってことで、以下のスクリプトで使った。

## mv with append characters
function amv() {
    local pos="end"
    while getopts b: opt; do
        case $opt in
            b)
                pos="begin"
                shift
                ;;
        esac
    done

    local args="$*"
    local files="${args% *}"
    local append="$argv[$#]"

    for file in $files; do
        if [ "$pos" = "begin" ]; then
            mv $file "$append$file"
        else
            mv $file "$file$append"
        fi
    done
}

ファイル名先頭か末尾に指定の文字列をくっつけて mv する。ただ、そんだけ。くっつける文字列はオプションで指定してもよかったけど、mv っぽく作りたかったのでコマンドラインの引数リストの最後に指定したかったので。。

もっと簡単にできるのかしら。。。

参考