BLOGTIMES
2014/06/28

bash で sub(), gsub(), substr() を直感的にする

  sh 
このエントリーをはてなブックマークに追加

シェルスクリプトを書いていてちょっとした固定長の文字列の加工に困ることがあります。
例えば日付の YYYYMMDDYYYY-MM-DD に変換したいときに、substr() があればなぁと思うわけです。

実は bash にはパラメータ展開という便利な機能があるので、これを使うと sub(), gsub(), substr() に相当する機能は簡単に実現できます
ただ、使い方がちょっと直感的でないので、使い方を忘れてしまうのですよね。

そんなわけで、他の言語と同じように sub(), gsub(), substr() という名前で使えたら便利なのではと思って関数化してみました。

substr(){ echo -n ${1:$2:${3:-${#1}}}; } #substr( str, pos[, len] ) gsub(){ echo -n ${1//$2/$3}; } #gsub( str, pat, sub ) sub(){ echo -n ${1/$2/$3}; } #gsub( str, pat, sub )

シグニチャ的には substr( str, pos[, len] )、gsub( str, pat, sub )、gsub( str, pat, sub ) というイメージです。
パターンの部分ははシェルのワイルドカード(*,?)が使えます

実際に使ってみるとこんな感じになります。
シンタックスシュガーのようなものですが、スクリプトの可読性は良くなるのではないでしょうか。

$ substr 123456123456 3 456123456 $ substr 123456123456 -3 456 $ substr 123456123456 0 3 123 $ substr 123456123456 2 4 3456 $ substr 123456123456 -3 2 45 $ gsub 123456123456 '123' 'ABC' ABC456ABC456 $ sub 123456123456 '123' 'ABC' ABC456123456 $ gsub 123456123456 '4?6' 'ABC' 123ABC123ABC $ sub 123456123456 '4?6' 'ABC' 123ABC123456 $ gsub 123456123456 '1*' 'ABC' ABC $ sub 123456123456 '1*' 'ABC' ABC

参考

${parameter:offset:length}
部分文字列展開。 parameter を展開したものから最大 length 文字を取り出します。 先頭の文字は offset で指定します。length を省略すると、 offset で指定した文字を先頭にして、 parameter の残り全部が含まれる部分文字列に展開します。 length と offset は算術式です (後述の 算術式評価 を参照)。 offset を評価すると 0 未満の数になる場合、この値は parameter の値の末尾からのオフセットとして使われます。 length を評価すると 0 未満の数になる場合、 parameter が @ ではなく、配列でも連想配列でもなければ、 この値は文字数ではなく parameter の値の末尾からのオフセットとして使われ、 展開結果は 2 つのオフセットの間の部分文字列となります。 parameter が @ ならば、結果は offset から始まる length 個の位置パラメータになります。 parameter が @ または * のインデックスが付いている配列名ならば、 結果は配列の ${parameter[offset]} を先頭とする要素 length 個となります。 負の offset は、指定された配列の最大のインデックス + 1 からの相対値と解釈されます。 連想配列に部分文字列展開した場合の結果は決められていません。 負のオフセットを指定するときには、:- 式と混同されないよう、 1 つ以上の空白でコロンと離す必要があることに注意してください。 位置パラメータを使う場合以外は、 部分文字列のインデックスは 0 から始まります。位置パラメータの場合には、 インデックスは 1 から始まります。 位置パラメータが使われて offset が 0 の場合、 $0 の値が先頭に置かれます。
${parameter/pattern/string}
パターンの置換。 pattern が展開され、 パス名展開の場合と同じようなパターンを作ります。 parameter の展開が行われ、 その値のうち pattern に最長一致する部分が string に置換されます。 pattern が / で始まる場合には、pattern に マッチした部分は全て string に置換されます。 そうでない場合には、最初にマッチした部分だけが置換されます。 pattern が # で始まる場合には、パターンは parameter を展開した値の先頭にマッチしなければなりません。 pattern が % で始まる場合には、パターンは parameter を展開した値の末尾にマッチしなければなりません。 string が空の場合には pattern にマッチした部分は削除されます。 またこの場合には、pattern の後に続く / は省略可能です。 parameter が @ または * である場合、置換操作は全ての位置パラメータに順番に適用され、 展開結果はリストとして得られます。 parameter が @ または * が添字になっている配列変数である場合、 置換操作は配列の全ての要素に順番に適用され、 展開結果はリストとして得られます。

    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/6821
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン