arison.jp arison.jp blog - 現在をたのしく、未来をたのしむ。日常の思い出兼備忘録。

bashで変数の一部を抜き出す時はパラメタ展開で

bash使ってて、ある変数の一部を抜き出す処理を行う時は
パラメタ展開(Shell Parameter Expansion)を使うべし。
cut は使わないこと。

1レコード1行で固定長のデータを編集したいとき、
シンプルに考えたら、1行を読み込んで何らかの変数に格納して
変数の何桁目から何桁目を抜いて、条件に応じて、ほげほげ・・・みたいなことをすると思います。

そんなとき、ある変数の一部を抜き出して変数に格納する場合

cutコマンドを使用する方法 (と パラメタ展開) がざっと思いつきました。
…パラメタ展開はcutコマンドで時間かかりすぎたので採用した。

cutコマンドを使用する方法

hoge="//arison.jp" 

work=`echo ${hoge} | cut -c 2-4 `

echo ${work}

ris

みたいな感じでやると、変数workに変数hogeの2文字目から4文字目までが取得できる。

でも、これだと遅い。

パラメタ展開
Bash Reference Manual
http://www.gnu.org/software/bash/manual/bash.html
3.5.3 Shell Parameter Expansion に記載されている方法

パラメタ展開(Shell Parameter Expansion)を使用する方法

hoge="//arison.jp" 

work=${hoge : 1 3}

echo ${work}

ris

を使うほうがバリ早でした。

cutが遅い原因は`~`にあり。
`(バッククォート)を用いると、コマンドの実行結果を変数に設定することができて便利です。
が、コマンドの実行結果をとるために別プロセスを立ちあげて実行するためプロセスの fork が必要。
で、fork のコストは相当高い。よって処理が遅くなります。

一方、パラメタ展開は自分自身でやっちゃう。

野菜炒め作るときに
他人に野菜切っといてと頼んで、切られた野菜をもらうより、
自分で野菜を切ったほうが早い
そんな感じで受け止めています。

で、結果は同じだけど、cutとShell Parameter Expansionでは数字が異なります。

cut の場合は1文字目をとりたい場合は1になります。
パラメタ展開の場合は1文字目をとりたい場合は0になります。
(配列が0からはじまるというアレです)

開始と終了の範囲を指定する方法
 cut の場合は「開始位置-終了位置」。
 パラメタ展開の場合は「開始位置 開始位置からの文字数」。


cutの方が、パラメタ展開より、引数の与え方がわかりやすいと個人的には感じています。

cutコマンドの詳細は下記を参考。
シェル・スクリプト・リファレンス – 【 文字列を抜き出す「cut」 】:ITpro
http://itpro.nikkeibp.co.jp/article/COLUMN/20060228/231159/

-b バイト数 指定したバイト数の文字を取り出す。バイトの指定には「開始位置-終了位置」のように範囲で指定できる
-c 文字数 指定した文字数の文字を取り出す。文字数の指定には「開始位置-終了位置」のように範囲で指定できる

-d “, ” デミリタ(区切り文字)を指定する。
-f フィールド 指定したフィールドの文字を取り出す。フィールドの指定には「開始位置-終了位置」のように範囲で指定できる

いろんな抜き出し方法ができるし、複数行扱えるので、cut自体は素晴らしいコマンドだと思います。


Shell Parameter Expansion は、いろいろできる分、わかりづらい。

公式には説明するために、こんなにたくさん書いていて・・・

$ string=01234567890abcdefgh
$ echo ${string:7}
7890abcdefgh
$ echo ${string:7:0}

$ echo ${string:7:2}
78
$ echo ${string:7:-2}
7890abcdef
$ echo ${string: -7}
bcdefgh
$ echo ${string: -7:0}

$ echo ${string: -7:2}
bc
$ echo ${string: -7:-2}
bcdef
$ set -- 01234567890abcdefgh
$ echo ${1:7}
7890abcdefgh
$ echo ${1:7:0}

$ echo ${1:7:2}
78
$ echo ${1:7:-2}
7890abcdef
$ echo ${1: -7}
bcdefgh
$ echo ${1: -7:0}

$ echo ${1: -7:2}
bc
$ echo ${1: -7:-2}
bcdef
$ array[0]=01234567890abcdefgh
$ echo ${array[0]:7}
7890abcdefgh
$ echo ${array[0]:7:0}

$ echo ${array[0]:7:2}
78
$ echo ${array[0]:7:-2}
7890abcdef
$ echo ${array[0]: -7}
bcdefgh
$ echo ${array[0]: -7:0}

$ echo ${array[0]: -7:2}
bc
$ echo ${array[0]: -7:-2}
bcdef

・・・めっちゃ丁寧にありがとうございます。
他にも特殊な参照方法があるので、覚えてられない。

それよりは、下をみたほうがわかりやすい。

ステップ・バイ・ステップ・シェルスクリプト(5):シェルの変数に慣れる – @IT
http://www.atmarkit.co.jp/ait/articles/0010/19/news003.html

何十万レコードとかのデータを扱うと、ちょっとの差でも大きな差になってきます。
バッチ処理などで、ある変数の一部を抜き出す処理を行う時はパラメタ展開(Shell Parameter Expansion)を使うべし。

速度比較しているサイトがありました。

【参考サイト】
cutコマンドで文字列を抜き出す? ちょっと待って!Bashパラメータ展開で72倍早くできるかも
http://netbuffalo.doorblog.jp/archives/4270874.html

About arison

大都会岡山の南部にある玉野市生まれ。 大都会岡山のIT会社(目標は大都会No.1)でコンピュータとお客を相手に日夜格闘中。 関東出張中はグルメブログ。 基本的に遊び人のおっさん。 ライフハックとガンダム好き。ギガフロート玉野を浸透中。

04. 6月 2015 by arison
Categories: プログラミング | 1 comment

1 Responses to bashで変数の一部を抜き出す時はパラメタ展開で

  1. 匿名 より:

    >bash使ってて、ある変数の一部を抜き出す処理を行う時は パラメタ展開(Shell Parameter Expansion)を使うべし。
    このおかげで爆速になりました。ありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください