ちょっと前にzawで更新順にブランチを表示してチェックアウトするやつを作ったのだけれど、その時参考にしたzshのスクリプトが全く読めなかったので読みといてみた。
local branches_list="$(git show-ref | awk ' $2 != "refs/stash" { print $2 }' )" : ${(A)cand_descriptions::=${${(f)${branches_list}}#refs/(remotes|heads|tags)/}}
まずlocalは変数定義。
次に$()はコマンド実行なので、中に含まれているコマンドを実行する。さらにそれが""で囲まれているので、出力結果を文字列として変数に格納する。
次の行。最初の:は何もしないコマンド。これがないと変数展開の結果をコマンド実行しようとしてしまう。
${}は変数展開。この中でいろいろする。
最初に(A)と付いているのはcand_descriptionsを配列として扱うという定義。
::=というのは、cand_descriptionsに代入するという意味。これわかりづらいんだけど、同じ場所に=が入ってたら変数がunsetされている場合のみ代入、:=ならunsetの場合か、定義されているけどnullの場合に代入される。全く直感的でない。
その後の${}はまた変数展開。branches_listを使った変数展開をする。しかも2段。
中の${}の部分、つまり ${(f)${branches_list}} の部分はbranches_listを改行区切りでsplitするというもの。(f)を付けることによりそういう風になる。
外の${}の部分はsplitされた配列の中をそれぞれパターンにmatchしたら削除するというもの。#以降がパターン。#の場合は最短マッチで、##の場合は最長マッチらしい。そんなの知るかって感じ。
参考
- 変数展開系はman zshexpnで
- :とかの関数系はman zshbuitinsとか