zsh文法帳なのですー>ω<
moonline.zshというものを作っていますですので、zshの文法を理解していなければいけないのですが、わたしはまだzshを使い始めて一週間にもならない未熟者なのですので、学習したことをメモしておきたいと思いますですー>ω<
色々と偏っているかもしれませんですし、(恐らく永遠に)書きかけの記事なので、あまりあてにしない方がいいかもしれないのですー>ω<
また、シェルスクリプトもzshも初心者なので、どこもかしこも間違っていそうな気がしていますです。なので、間違いを指摘していただけると、わたしとしては至極嬉しい限りなのです!
コメント
# コメントは # から始めますですー>ω< # ちなみに、 下記のオプションを設定しないと対話シェル中ではコメントが有効にならないので注意なのです setopt interactive_comments
コマンドの実行
# 普段、端末で行なうのと同じです mkdir test # mkdir はディレクトリを作るコマンドです (MaKe DIRectoryの略だと思われます) cd test # cd はディレクトリを移動するコマンドです (Change Directoryの略だったと思いますです) # ; で区切って複数実行できますです touch test.txt; ls # touch はファイルの編集時刻を更新するコマンドです。ファイルが無い場合は作成する、という機能もありますです # ls はディレクトリのファイルなどの一覧を表示するコマンドです # && で、左のコマンドが正常に行なわれたら、右のコマンドを実行する、といったことができますです mkdir test2 && cd test2
出力
# 出力には echo コマンドを使いますです echo "Hello World" # 改行なしにする場合は、 -n オプションを付けますです echo -n "Hello World"
変数
# 代入(連想配列以外なら宣言は必要ないのです) # 変数名と = の間に、空白を入れないことが大切なのです x=1 # 複数使う場合は、空白区切りで並べられますです(別に改行で区切っても問題ないです) y=2 z=3 # 初期化したい場合は、左辺に何も書かないのです(単に変数名だけだと、その名前のコマンドと解釈されてしまいますです) w= # 参照は$を付けますです echo $x #=> 1 # 空白を含む場合は、 "" で囲うのです x="Hello World" echo $x #=> Hello World # 変数から変数への代入は、参照するのと同様のイメージなのです y=$x echo $y #=> Hello World # "" の中でも変数を展開できるのです echo "$x - こんにちは世界" #=> Hello World - こんにちは世界 # ただし、 '' の中では展開されないのです echo '$x' #=> $x # 存在しない変数は "" (長さゼロの文字列)として扱われるのです(エラーが出ない) echo $xxx #=> (何も表示されない) # 展開するとき、どこまでが変数名か分からなくなるなら、 {} で変数名を囲うのです echo "$xWideWeb" #=> (何も表示されないのです。なぜなら、存在しない $xWideWeb という変数を参照しているからなのです) echo "${x}WideWeb" #=> Hello WorldWideWeb
配列
# () で囲って、要素を空白で区切りますです xs=(1 3 5) # 要素の参照は、1から始まりますです echo $xs[1] #=> 1 echo $xs[2] #=> 3 echo $xs[3] #=> 5 # 要素に代入することもできますです xs[1]=2 echo $xs[1] #=> 2 # 配列の入った変数をそのまま参照すると、空白区切りの文字列となりますです echo $xs #=> 2 3 5 # 要素数は、 $# で参照しますです(冷静に考えると、ここでの # はコメントとして解釈されないのですね。不思議です(`・ω・′)) echo $#xs #=> 3 # 要素の追加には += を使いますです。この場合は末尾に追加されるのです xs+=(7) echo $xs #=> 2 3 5 7 echo $#xs #=> 4 # 配列を別の変数に代入するときは、()で囲むのです # ちなみに、要素に空白を含むものがあっても問題ないのです ys=($xs) echo $ys #=> 2 3 5 7 # さっきのはRubyやPythonなどのようにオブジェクトを参照しているのではなく、コピーを取っているので、要素に代入しても一方に反映される、といったことはないのです ys[1]=1 echo $ys #=> 1 3 5 7 echo $xs #=> 2 3 5 7 # 配列のループには、 for文(これはzshに組み込まれたものなので、コマンドではなく文法なのだと思いますです)を使いますですー>ω< # これは、pythonで言うfor in文、PHPのforeach文のようなものなのではないかと思いますです for x in $xs; do # x に各要素が代入されていますです echo -n "${x}x" done #=> 2x3x5x7x # どうしてもインデクッスでループをしたいのなら、次のように書くこともできますです # (ただし、あまりこの書き方はしないような気がしますです) for ((i = 1; i <= $#xs; i++)); do echo "$i --> $xs[$i]" done #=> 1 --> 2 #=> 2 --> 3 #=> 3 --> 5 #=> 4 --> 7
関数
# zshの関数の定義方法は、2つありますです # 1つは、function文を使う方法です function fn1() { # 引数は $1,$2...$9 で取得することができますです echo "1 --> $1" echo "2 --> $2" } # 呼び出しは、コマンドのようになりますです fn1 a b #=> 1 --> a #=> 2 --> b fn xxx yyy #=> 1 --> xxx #=> 2 --> yyy # もう1つは、functionを省略した形です。こちらの方が(何となくですけど)伝統的なような気がしていますです fn2() { echo fn2 } fn2 #=> fn2 # この2つの違いはよく分からないのです(′・ω・`) # どなたか教えて下さると幸いです # 今回は、省略した形の方が短かく書けるし、そうしないとVimのインデントが上手く働いてくらなかったのでそちらを採用しますです # 関数の中で変数を使うときに、グローバル変数を壊したくないのなら、 local で宣言するのです x="global variable" y="global variable" fn3() { # こんな風に local x x="local variable" echo "x is $x" #=> x is local variable # 宣言と代入を同時に行なうこともできますです local y="local variable" echo "y is $y" #=> y is local variable # 複数の変数を同時に宣言することもできますです # 初期値はあっても無くても問題ないのです local z w=local # ただし local の場合、配列は同時に代入することができないのです # local xs=(1 2 3) # これはエラーになるのです # この場合、宣言と代入を2回に分けて行なうといいのです local -a xs # -a オプションは、配列の変数を宣言していることを表わしますです。今回はすぐに代入してしまうので関係ありませんが、空の配列として初期化されますです xs=(1 2 3) echo $xs #=> 1 2 3 echo $#xs #=> 3 } # localで宣言しているので、変数は上書きされないのです fn3 # fn3の呼び出し echo "x is $x. y is $y too" #=> x is global variable, y is global variable too # 可変長引数は、$* か $@ という特殊な変数を使って参照できますです。また、引数の個数は $# なのです # fn4 は与えられた引数を全て表示する関数 fn4() { local i arg # for文で使うループ変数も local で宣言しておかないと、グローバルな変数として扱われてしまうので注意です for ((i = 1; i <= $#; i++)); do echo "$i --> $*[$i] $@[$i]" done } # fn4を呼び出してみますです。$@と$*が "この場合は" 違わないことが分かりますです fn4 1 a "Hello World" #=> 1 --> 1 1 #=> 2 --> a a #=> 3 --> Hello World Hello World # もう1つ実験してみますです # $* と $@ で引数を展開して、fn4 に渡す関数 fn5() { echo '$*'; fn4 $* echo '$@'; fn4 $@ } fn5 1 a "Hello World" #=> $* #=> 1 --> 1 1 #=> 2 --> a a #=> 3 --> Hello World Hello World #=> $@ #=> 1 --> 1 1 #=> 2 --> a a #=> 3 --> Hello World Hello World # $* と $@ は、配列として参照する場合には違いはないのです # では、どんなときに違いが表れるのかというと、""に囲んで展開したときに変化があるのです # fn6 は与えられた引数を "$*" で fn4 に渡す関数 fn6() { echo '"$*"'; fn4 "$*" } # fn7 は与えられた引数を "$@" で fn4 に渡す関数 fn7() { echo '"$@"'; fn4 "$@" } # この fn6 と fn7 を使うと、"$*" と "$@" の違いが顕著に表れますです fn6 1 a "Hello World" #=> "$*" #=> 1 --> 1 a Hello World fn7 1 a "Hello World" #=> "$@" #=> 1 --> 1 1 #=> 2 --> a a #=> 3 --> Hello World Hello World # "$*" のときは1つのパラメーターとして、 "$@" のときは複数のパラメーターとして展開されていますです!
(書きかけ…。まだまだ書きたいことはあるのです…。文字列関連とか、ともかく色々)