zsh 実験メモ:文字列変数の中から空白文字の位置を探したい時…
ふと迷ったのでメモ。ツッコミ希望です。
foo='key foo bar baz...'
のような文字列変数が有るとして、これを key
と
"foo bar baz..."
の2つに分割したい。
要するに perl の split " ", $foo, 2
がしたい。
一旦配列変数に展開してから、2つ目以後を取り出して join し直す、だと、途中に複数のスペースや改行があっても 一文字にされてしまうので、いつでも使えるとは限らないなあと。
ary=($=foo) print $ary[2,-1]
文字列の中から、特定の文字の位置を探すのは、 subscript の (r) や (i) フラグを使えばいける、
けど、スペースを subscript に書くとパースエラーになる。 \
や " "
だとマッチしないし。
% foo='key foo bar baz...' % print $#foo 22 % print $foo[(i) ] zsh: invalid subscript % print $foo[(i)\ ] 23 % print $foo[(i)" "] 23 % print $foo[(i)' '] 23 %
一時変数を作ってそこにスペース文字を入れれば行ける、けど、凄く負けた感が有る。
% k=' ';print $foo[(i)$k] 4
自分が思いついた解決策
${:-文字列式}
を使う。ベストかどうか、分かりませんが。
% print $foo[(i)${:- }] 4 % print $foo[(r)${:- },-1] foo bar baz... % pos=$foo[(i)${:- }] % print key=$foo[1,pos-1] value=$foo[pos+1,-1] key=key value=foo bar baz... % % print key=${(qq)foo[1,pos-1]} value=${(qq)foo[pos+1,-1]} key='key' value='foo bar baz...' %
(key 側に off by one が有ったので訂正)
追記:上記を位置パラメータに使うには ${...} が必要…
% set -- --define 'dist .fc22.hk1' % print $2[(i)${:- }] zsh: no matches found: dist .fc22.hk1[(i) ] % print ${2[(i)${:- }]} 5 % typeset -A defines % p=${2[(i)${:- }]} % defines[${2[1,p-1]}]=${2[p+1,-1]} % print ${(kvqq)defines} 'dist' '.fc22.hk1' %