LoginSignup
38
33

More than 5 years have passed since last update.

zshとbashでは変数の単語の分割ルールが違う

Last updated at Posted at 2014-12-04

変数の値にスペースが含まれているとき、zshとbashで単語の分割ルールが違う。zshでシェルスクリプトを書くときに注意が必要になるので紹介する。

例1: 変数をコマンドの引数に指定する

変数の値にスペースを入れて、それをtouchコマンドの引数にしてみる。

zshの場合は変数の値が1つの単語として扱われる。なのでfile1 file2という1つのファイルが作成される。

% filename="file1 file2"
% touch $filename
% ls -l
-rw-r--r-- 1 mollifier mollifier 0 12月  4 10:36 file1 file2

bashやshの場合は変数の値が中に含まれるスペースで区切られる。なのでfile1file2という2つのファイルが作成される。

# bashまたはshの場合
% filename="file1 file2"
% touch $filename
% ls -l
-rw-r--r-- 1 mollifier mollifier 0 12月  4 10:37 file1
-rw-r--r-- 1 mollifier mollifier 0 12月  4 10:37 file2

つまり、zshの場合はtouch "file1 file2"、bashの場合はtouch "file1" "file2"というふうに変数の値が展開される。

例2: コマンドを変数に代入して実行する

コマンドと引数を変数に代入して実行する場合も同じで、zshの場合は変数の値を1つのコマンドとして実行しようとする。

# zshの場合
% cmd="echo hoge"
% $cmd
zsh: command not found: echo hoge

bashやshの場合は変数の値を中に含まれるスペースで区切ってから実行する。

# bashまたはshの場合
% cmd="echo hoge"
% $cmd
hoge

zshでbashと同じようにスペースで区切る

zshでもbashと同じように変数の値を分割することもできる。方法は2つ。

方法1

SH_WORD_SPLITオプションを有効にすると変数を分割するルールがbashと同じになる。

setopt SH_WORD_SPLIT
% cmd="echo hoge"
% $cmd
hoge

方法2

変数を${=VAR}という形式で参照すると、SH_WORD_SPLITオプションを有効にしたときと同じように変数の値が展開される。

% cmd="echo hoge"
% ${=cmd}
hoge

「方法1」はオプションを無効にするまでその設定になってしまうので、SH_WORD_SPLITオプションはデフォルト(無効)のままで必要があるときだけ「方法2」のやり方で展開するのがよいと思う。

たまに、この方法を知らないと思われる人がevalしてるのを見ることがある。

% cmd="echo hoge"
% eval $cmd

evalは無理矢理な感じがするので、${=cmd}を使ってみてください!

bashでもzshと同じようにスペースで区切らないようにする

bashでも変数を"で囲むと、zshと同じように変数の値が分割されないようになる。

# bashまたはshの場合
% filename="file1 file2"
% touch "$filename"
% ls -l
-rw-r--r-- 1 mollifier mollifier 0 12月  4 10:37 file1 file2

なので、bashまたはsh用のシェルスクリプトを書くときは、基本的には変数名を"で囲っておいたほうが安全。

38
33
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
33