【シェルの文字列操作のショートハンド集】Bashの文字列のパラメーター拡張のアレコレ


2021/03/29

Bashで扱う文字列操作には、
パラメーター拡張(Parameter Expansion)という簡潔な操作で様々な機能を提供する仕組みが備わっています。

Bashを使ってシェルスクリプトを操作する際に、このパラメーター拡張を知っておかないと損をしますので、この記事で使えそうなテクニックをいくつかピックアップしてみようかと思います。


はじめに

当サイトではオフィス業務のComputer-Aidedなハイブリッドな方法を模索し、より効率的なExcel業務を実現したい多忙なオフィスワーカー向けの主にAwkとSedを使うシェル講座です。

シェルスクリプトはどこでもどんなOSでも基本的に使えて、しかも一度使い方を覚えると、Excelと組み合わせて最高に効率の良いオフィスワークツールが作れることでしょう。

合同会社タコスキングダム|蛸壺の技術ブログ


文字列の置換

まずなんと言っても良く利用するパターンが、文字列置換です。

            
            利用法①:
    #最初にマッチした箇所のみ置換
    ${変数名/パターン/置換}

利用法②:
    #マッチした全ての箇所を置換
    ${変数名//パターン/置換}
        
文字列に対してパラメーター拡張で置換を行う場合は、検索パターンと置換後の文字列を指定して使います。

スラッシュ文字('/')を使うやり方では2通りの置換法があり、変数名の後に'/'で見つかったパターンのうち最初だけ置換し、'//'で見つかったパターン全てを置換することができます。

使用例

            
            $ HOGE_FILE="/path/to/hoge.piyo.fuga.mofu"
$ echo "${HOGE_FILE/./-}"
#👇先頭から最初に見つかった.を-で置換
/path/to/hoge-piyo.fuga.mofu

$ echo "${HOGE_FILE//./-}"
#👇先頭から見つかった.を全て-で置換
/path/to/hoge-piyo-fuga-mofu
        

文字列の(前方・後方一致部分の)置換

先程の置換の別パターンですが、文字の前後から完全に一致する箇所を置き換えます。

            
            利用法①:
    #前からマッチした箇所を置換
    ${変数名/#パターン/置換}

利用法②:
    #後ろからマッチした箇所を置換
    ${変数名/%パターン/置換}
        

使用例

            
            $ HOGE_FILE="/path/to/hoge.piyo.fuga.mofu"
$ echo "${HOGE_FILE/#\/path/-}"
#👇先頭から完全に一致した/pathまでを-で置換
-/to/hoge.piyo.fuga.mofu

$ echo "${HOGE_FILE/#path/-}"
#👇先頭から完全に一致していないので置換は行われない
/path/to/hoge.piyo.fuga.mofu

$ echo "${HOGE_FILE/%a.mofu/-}"
#👇末尾から完全に一致したa.mofuまでを-で置換
/path/to/hoge.piyo.fug-

$ echo ${HOGE_FILE/%a.mof/-}
#👇後ろからの検索パターンが一致しなければ置換は実行されないので注意
/path/to/hoge.piyo.fuga.mofu
        
また配列に適用すると配列要素の全てを変化させて返します。

            
            $ BROS=(太郎 次郎 三郎)
$ echo "${BROS[@]/#/甘}"
#👇先頭に'甘'という文字を追加
甘太郎 甘次郎 甘三郎
        

文字列の長さをカウント

文字列の長さを表示させる使い方は以下のようになります。

            
            利用法:
    ${#変数}
        

使用例

            
            $ GREETING="本日から本気出す。"
$ echo ${#GREETING}
#👇日本語も正しくカウントされる
9
        


部分文字列

文字列から部分文字列を取り出します。

            
            利用法①:
    #オフセット位置からの部分文字列を返す。
    #先頭位置は0
    ${変数:オフセット位置}

利用法②:
    #オフセット位置からの指定した文字列長までの部分文字列を返す。
    #先頭位置は0
    ${変数:オフセット位置:文字列長}
        

使用例

            
            $ HEX_EXP='0123456789abcdef'

$ echo "${HEX_EXP:5}"
#👇開始位置(5)から文字列の最後まで抽出
56789abcdef

$ echo "${HEX_EXP:5:6}"
#👇開始位置(5)から数えて6進んだ位置(a)まで抽出
56789a
        

文字列パターンの削除(前方検索・後方検索)

先程の置換のやり方と似ていますが、こちらは削除により特化した機能です。

            
            利用法①:
    #パターンを前方から検索し、最初に最短マッチした文字列を削除
    ${変数#パターン}

利用法②:
    #パターンを前方から検索し、最初に最長マッチした文字列を削除
    ${変数##パターン}

利用法③:
    #パターンを後方から検索し、最初に最短マッチした文字列を削除
    ${変数%パターン}

利用法④:
    #パターンを後方から検索し、最初に最長マッチした文字列を削除
    ${変数%%パターン}
        

利用例

            
            $ TODAYS_MEMO='今日のわんこ。今日のにゃんこ。今日のはとぽっぽ。'

$ echo ${TODAYS_MEMO#今日の*。}
#👇先頭から最短マッチで 今日のわんこ。の部分が削除される
今日のにゃんこ。今日のはとぽっぽ。

$ echo ${var##今日の*。}
#👇先頭から最長マッチで全ての文字が削除される(何も表示されない)

$ echo ${TODAYS_MEMO%今日の*。}
#👇末尾から最短マッチで 今日のはとぽっぽ。の部分が削除される

$ echo ${TODAYS_MEMO%%今日の*。}
#👇末尾から最長マッチで全ての文字が削除される(何も表示されない)
        

デフォルト値の置き換え

変数が未設定やヌルだった場合に、指定した代替文字で置き換えてくれる機能です。

            
            利用法①:
    #変数に値が設定してない・ヌルが設定してある場合に、
    #デフォルト値として呼び出されます
    ${変数:-デフォルト値}

利用法②:
    #変数に値が設定してない・ヌルが設定してある場合に、
    #デフォルト値として呼び出され、
    #かつ、その変数にデフォルト値が設定されます。
    ${変数:=デフォルト値}

利用法③:
    #上の2つとは逆に変数に値が設定・定義してある状態の場合に、
    #デフォルト値として呼び出されます。
    ${変数:+デフォルト値}
        

使用例

ユースケースとしては初期化されていない変数などを操作したい場合に利用できます。

            
            #👇明示に変数の値を未設定にする
$ unset HOGE

$ echo "${HOGE:-PIYO}"
#👇変数HOGEは未設定なのでPIYOがデフォルトとして表示
PIYO

$ echo "$HOGE"
#👇続けて変数HOGEを呼び出してもデフォルト値は設定されていない

$ echo "${HOGE:=FUGA}"
#👇変数HOGEは未設定なのでFUGAがデフォルトとして表示
FUGA

$ echo "$HOGE"
#👇続けて変数HOGEを呼び出すと、今度は直前の操作でデフォルト値も設定されている
FUGA

$ echo "${HOGE:+MOFU}"
#👇変数HOGEにFUGAが設定されているので、デフォルト値はMOFUで置き換わる
MOFU

#👇再び変数HOGEの値を未設定にする
$ unset HOGE

$ echo "${HOGE:+MOFU}"
#👇再度実行すると今度は変数HOGEが未設定なのでデフォルト値は置き換わらない
        

変数の間接的な呼び出し

定義していた変数を、文字列などから呼び出したい場合に利用できるテクニックです。

            
            利用法:
    ${!変数}
        
どのように動作するかは以下の利用例を見ていただいたほうが早いです。

利用例

            
            $ HOGE=32
$ piyo='HOGE'

$ echo "${piyo}"
#👇当然piyoの保持する文字列が返される
HOGE

$ echo "${!piyo}"
#👇piyoの持つHOGEという文字列から変数HOGEが間接的に呼び出される
32
        
これにより動的な変数の参照が可能になります。

            
            $ args_test () {
    for (( i=1; i<="$#"; i++ )); do
        echo "${i}"
    done
}; args_test -x -y -x
#👇変数iの値が呼び出される
1
2
3

args_test () {
    for (( i=1; i<="$#"; i++ )); do
        echo "${!i}"
    done
}; args_test -x -y -x
#👇$1$2$3の引数が呼び出される
-x
-y
-x
        

まとめ

今回はBashの文字列の基本機能であるパラメーター拡張に関するテクニックまとめでした。

以上で見ていただいた通り非常に強力な機能ばかりですので、Bashを使っているならば使わないと損です。この機会にぜひともガンガン使っていくと良いと思います。


参考サイト

Bash Parameter Expansion

記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。