Skip to content

Instantly share code, notes, and snippets.

@sho-t
Last active September 20, 2023 12:56
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sho-t/d9cdf8271b3de7c4238739e523490542 to your computer and use it in GitHub Desktop.
Save sho-t/d9cdf8271b3de7c4238739e523490542 to your computer and use it in GitHub Desktop.
Zsh 変数メモ

variable

変数に関するメモ。 💤がついてるのはzsh 固有のもの。

📮 シェル変数と環境変数

  • シェル変数 → 子プロセスに継承されない
  • 環境変数 → 子プロセスに継承される

環境変数登録 export NEWENV=hogehoge

おまけ 環境変数の値を表示するコマンド printenv 変数名

🇶🇦 クォート

  • '...' シングルクォート :内部での展開なし
    • オプション RC_QUOTES をセットしてる場合、内部で ''' として展開される
    • 空白文字があっても単語分割では1語としてみなされる
  • "..." ダブルクォート : 内部での展開あり
    • グロッビング(* とか ? )は展開されない
  • $'...'
    • printコマンドと同じエスケープシーケンスが使える echo $'\e[4munderline'  -> underline

🎊 値の展開(variable expansion)

manのここ(14.3 Parameter Expansion) たくさんあります。 以下変数名を name とする。

🇩🇪 単純展開、デフォルト値の操作

${name}

  • 変数が配列の場合は各要素を1単語としてすべての要素を並べた文字列に展開。ただしオプション KSH_ARRAYS がセットされている場合は、配列の先頭要素のみを展開する。
  • 値の文字列に空白が含まれる場合、デフォルトでは語分割されない:zzz:

${+name} 💤

  • 変数が定義済みの場合 1、定義されてなければ_0_に展開される。

${name-word}
${name:-word}

  • デフォルト値(代入なし)
  • - は値が設定されていない場合、 :-は値がNULLの場合に _word_が展開される。

${name=word}
${name:=word}
${name::=word} 💤

  • デフォルト値(代入あり)
  • = は値が設定されていない場合、 := は値がNULLの場合に _word_が展開かつ代入される。
  • ::= は変数に空文字以外の値が入ってる場合でも上書き代入する。

${name?word}
${name:?word}

  • ? は値が設定されていない場合、 :? は値がNULLの場合に、 word をメッセージとして出力してシェルの実行を終了する。

${name+word}
${name:+word}

  • + 値が設定されている場合、 :+ 値がNULLでない場合 word に展開される。

📽️ 値の加工

${name#pattern}
${name##pattern}

  • 値の先頭が pattern で始まっていれば削除して展開する。
  • # は最短マッチ。 ## は最長マッチ。

${name%pattern}
${name%%pattern}

  • 値の末尾が pattern で始まっていれば削除して展開する。
  • % は最短マッチ。 %% は最長マッチ。

${name:#pattern} 💤

  • 値が pattern に完全マッチしていればすべて削除して展開する。
  • 「配列値から特定の値を削除」したい場合とかに使える。
% echo $arr
a b c
% echo ${arr:#b}
a c

${name:|arrayname} 💤

  • arrayname は配列変数名
  • 配列 name の要素から arrayname に存在する要素を除去する。
% food=(apple potato banana grape chiken)
% fruits=(apple banana grape melon)
% echo ${food:|fruits}
potato chiken

${name:*arrayname} 💤

  • :| の置換と同様。 こっちは 論理積。 両方に存在する要素のみ保持される。
% echo ${food:*fruits}
apple banana grape

${name:^arrayname} 💤
${name:^^arrayname} 💤

  • 2つの配列をzipする。 配列の要素が交互に選択される。

  • :^ 短いほうの配列の長さ × 2 の配列が生成される。

  • :^^ 長いほうの配列の長さ × 2 の配列が生成される。

% a=(a b c); b=(1 2)
% echo ${a:^b};
a 1 b 2
% echo ${a:^^b}
a 1 b 2 c 1

${name:offset}
${name:offset:length}

  • bashから言葉を拝借すると 部分文字列展開。
  • lengh 文字数を取り出す。 開始位置は offset で指定(先頭0)。

${name/pattern/new}
${name//pattern/new}
${name:/pattern/new} 💤

  • 値のうち pattern にマッチする部分を new に置き換える。
  • / は最初のマッチのみ、 // はマッチしたものすべて。
  • :/ は_pattern_ が文字列全体にマッチした場合のみ 置き換えられる。
  • pattern/を含ませたい場合は バックスラッシュを前置する。
echo $hoge
/hoge/hogehoge
% echo ${hoge/\/hoge/\/foo}
/foo/hogehoge

${#name}

  • 値の文字数(整数)に置換される。
  • 値が配列の場合は要素数に置換される。

${^name}:zzz:
${^^name} 💤

  • ^ オプション RC_EXPAND_PARAM を一時的に有効化して展開。
  • ^^ オプション RC_EXPAND_PARAM を一時的に無効化して展開。

${=name} 💤
${==name} 💤

  • 語分割の有効化
  • = オプション SH_WORD_SPLIT を一時的に有効化して展開。
  • == オプション SH_WORD_SPLIT を一時的に無効化して展開(zshデフォルト)。

${~name} 💤
${~~name} 💤

  • ~ オプション GLOB_SUBST を一時的に有効化して展開。
  • ~~ オプション GLOB_SUBST を一時的に無効化して展開。

🚩 変数展開フラグ(Parameter Expansion Flags) 💤

フラグを指定すると特別な展開処理を行える。

14.3.1 Parameter Expansion Flags (zsh)

書式:${(ここに記述)name} 補完も効きます。 ${(ここでTab or Ctrl-I めっちゃある。。

以下一覧

記号 意味
# 結果の単語を数値式として評価する
% プロンプト文字列展開 と同じ%エスケープを展開する。
@ 変数展開が "" 内で行われたとき、 個々の配列要素が別々の単語として展開される。
f 改行文字(\n)で単語分割する(field spliting) ps:\n:の短縮形
F 区切り文字に改行(\n)を使用して、配列の単語を結合する(fの逆)
A デフォルト値代入展開で配列パラメータを作成する(Array)
AAとした場合は連想配列となる
e 結果に対してパラメータ拡張コマンド置換、および算術展開を行う(eval)
P 展開結果を変数名とみなしてさらに展開(Parameter)
k 連想配列のキー配列を返す(keys)
v 連想配列の値を取り出す(values) kと併用する。
U 展開結果のすべての英字を大文字に変換する(Upper)
L 展開結果のすべての英字を小文字に変換する(Lower)
C 展開結果を単語区切りで先頭大文字にする(Capitalize)
「単語」の単位は 英数時以外で区切られた一連の英数字を指す。
o 結果の単語を昇順でソートする(order)
O 結果の単語を降順でソートする(oの逆)
a 配列インデックス順でソートする(array-order)
O と組み合わせて配列逆順取得とか
i ソート時に大文字小文字を区別しない(ignore-case)
n 数値とみなしてソートする(number)
q 特殊文字をクォートする(quote)
qq シングルクォートで括る
qqq ダブルクォートで括る
qqqq $' ' で括る
Q 結果の単語から1段階クォートを外す(qの逆)
t 変数の型を返す(type)
u 配列から重複除去(unique)
c ${#ARRAY}の時、すべての要素の文字数を加算した値が展開される
デフォルトでは要素数
V 制御文字等が含まれる場合に可視化(Visible)
w ${#VAR} で単語数を返す(words)
W w とほぼ同じ。連続した区切り文字間の空文字も1単語として数えられる。
X Q , e 展開時やパターンマッチングで発生するエラーを報告する。
z シェルの単語分割規則に従って結果を分割する。
p j l r s と併用した場合、フラグの引数に printコマンドと同じエスケープシーケンスが使える。
j:string: string を区切り文字として配列中の各単語を結合する(join)
l:N::string1::string2 配列各要素が_N_ 桁になるように、単語の左側を埋める。
string1 は埋め込み文字(任意オプション)
string2 は単語の左側に挿入される文字(任意オプション)
m 文字数カウントにバイト数を用いる
r:N::string1::string2 lと同様。 r の場合は右埋め
s:string string を区切り文字として単語分割する(split)
S ${~#~}${~%~} 使用時に、 両側から検索をかける
最長マッチを最短マッチに置き換える
I:N: 検索・置換時にマッチングをN番目のものに指定する。
B マッチした文字列の先頭からのインデックスを返す(Beginning)
先頭のインデックスは1
E マッチした文字列の末尾のインデックスを返す。(End)
M マッチした文字列だけを返す(Matched portion)
N マッチした文字列の長さを返す(leNgth) ← 強引w
R マッチしなかった部分を返す(Rest)

🎏 添字用変数展開フラグ (subscript flags) 💤

man のここ(15.2.3 Subscript Flags)

配列を取り出すときに用いる。補完も効きます。 書式 name[(flags)exp]

以下一覧

記号 意味
w 添字付き変数が文字列の場合、単語単位での取り出し指定になる。
デフォルトの単語区切りは空白文字。
s:string w フラグと併用する。 string に単語区切り文字列を指定。
p s フラグよりも前に指定。 print コマンドと同じエスケープシーケンスが使える。
f w フラグと同様。ただし 単語区切り文字が 改行文字。
r 添字部分(書式の_exp_)にパターンを指定。 パターンにマッチする最初の要素を取得する
R rフラグと同様。 末尾から検索をかける。
i, I rフラグと同様。ただしパターンにマッチしたインデックスを返す。
i : 先頭から検索をかける。見つからなかった場合は、_配列の長さ+1_を返す
I : 末尾から検索をかける。 見つからなかった場合は、0 を返す
k,K 連想配列の添字で使用する。 配列のキーをパターンとして解釈する。
マッチした最初のキーを取得する。 Kは マッチした全ての値を返す。
n:expr: r R i I フラグと組み合わせて使用する。 検索でマッチした expr 番目の要素を取得する。 見つからなかった場合は 空文字を返す。
b:expr: r R i I フラグと組み合わせて使用する。 検索開始位置を expr 番目の要素とする。
e パターンマッチングでプレーンストリングマッチングが使用される。
*@ が展開されない。

使ってみる

# w 単語単位取り出し
% var="red green yellow blue"
% echo ${var[3]}
d
% echo ${var[(w)3]}
yellow

# s 区切り文字指定
% var="red:green:yellow:blue"
% echo ${var[(ws,:,)3]}
yellow

# f 改行区切り
% echo "red\ngreen\nyellow\nblue" > file.txt
% echo ${$(<file.txt)[(f)3]}
yellow

# r R i I 検索
% var=(red green yellow blue)
% echo ${var[(r)?e*]} # 先頭から検索
red
% echo ${var[(R)?e*]} # 末尾から検索
yellow
% echo ${var[(i)?e*]} # 先頭から検索(インデックス返す)
1 # ※ zshでは 配列のインデックス先頭は 1 なのです 
% echo ${var[(I)?e*]} # 末尾から検索(インデックス返す)
3 

# n 取得インデックス指定 
% echo ${var[(rn:1:)?e*]}
red
% echo ${var[(rn:2:)?e*]}
yellow
% echo ${var[(rn:0:)?e*]} # exprが0のときも1番目が取れるみたい
red

# b 開始位置指定
% echo ${var[(rb:2:)*e*]}
green
% echo ${var[(rb:2:)*e*]}

## k K キーマッチング (使い所が難しそう)
% typeset -A hash=('?' one '??' two '*' jango)
% echo ${hash[(k)A]}
jango
% echo ${hash[(k)AA]}
two
% echo ${hash[(K)AA]}
two jango

🅾️ でてきたオプション

KSH_ARRAYSKSH_ARRAYS

 配列の添字が0ベースとなる。  添字無しで展開した場合に、先頭要素だけ展開される。

# off
% echo arrays:${arr}, first:${arr[1]}
arrays:a b c, first:a

# on
% set -o ksharrays; echo arrays:${arr}, first:${arr[1]};
arrays:a, first:b
RC_EXPAND_PARAM

やってみたほうがわかりやすい。

% arr=(ee u oo)
#off
% echo s${^^arr}n
see u oon

#on
% echo s${^arr}n
seen sun soon
SH_WORD_SPLIT

変数展開時に展開された値を空白文字で分割する。

onにした場合はbashと同じ動きになる。 参考はこちら

% word="one two three"
# off
% echo ${(qqq)==word}
"one two three"

# on
% echo ${(qqq)=word}
"one" "two" "three"
GLOB_SUBST

変数展開時に展開後の値でパス名展開する。

% files=./*;
# off
% echo ${~~files}
./*

#on
% echo ${~files}
./file.txt ./file2.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment