Advanced Bash Scripting Guide

Advanced Bash Scripting Guideというものを見つけました。manには書かれていない関数などがたくさん書かれています。

例えば、文字列検索(照合;match)などを、BASH_REMATCH を利用してちまちま作ってましたが、ものによっては、「expr match」、「expr index」という書式で、かなり簡潔に記述できるようです。

コマンドリファレンスに一覧があります。便利な関数がこれ程たくさんあるとは知らなかった・・・

興味深い関数の抜粋(Table B-5. String Operations)

expr match "$string" '$substr' Length of matching $substr at beginning of $string
expr "$string" : '$substr' Length of matching $substr at beginning of $string
expr index "$string" $substr Numerical position in $string of first character in $substr that matches [0 if no match, first character counts as position 1]
expr substr $string $position $length Extract $length characters from $string starting at $position [0 if no match, first character counts as position 1]
expr match "$string" '\($substr\)' Extract $substr, searching from beginning of $string
expr "$string" : '\($substr\)' Extract $substr, searching from beginning of $string
expr match "$string" '.*\($substr\)' Extract $substr, searching from end of $string
expr "$string" : '.*\($substr\)' Extract $substr, searching from end of $string

照合位置を返す関数を探していてコマンドリファレンスを見つけたのですが、残念ながら「expr index」は「$substr(正規表現)が照合した位置を返す」というものは異なるようです。

$ expr index "ab0ab1ab2" "ab1"
1

「4」が欲しいところですが、「1」です。なぜかということですが、これは、次のようにすれば解ります。

$ expr index "ab0ab1ab2" "1b"
2

indexは$substrに含まれるいずれかの文字が最初に出現する位置を返す関数ということでした。
所望の機能をスクリプトで書くと、次のようになります。

# 照合位置
# $1 ... 文字列
# $2 ... 正規表現
function str_index {
    [[ $1 =~ ($2.*$) ]] && {
	local mstr=${BASH_REMATCH[1]}
	local remains=${1%%${mstr}}
	echo $(( ${#remains}+1 ))
	return
    }
    echo 0
}

こんな感じでどうでしょう?ついでに、置換と削除も・・・となりますが、これはsed 使ってます。

$ echo "ab cd efg hi jkl mn" |sed -e 's/ //'
abcd efg hi jkl mn

全ての空白の削除は、gオプション付ければできます。

$ echo "ab cd efg hi jkl mn" |sed -e 's/ //g'
abcdefghijklmn