zshの単語分割 cut 相当

シェルスクリプトからパスワードエントリの gecos 部分を引っ張って来る。

getent passwd user | cut -d: -f5

cutの部分は awk -F: '{print $5}' でよし。

さて、これをzshの変数展開でやるには $( ) のコマンド起動に、変数展開フラグ @ W s を組み合わせる。

gecos="${${(@Ws,:,)$(getent passwd user)}[5]}"

zshの本 6.7のwフラグの説明(225〜226あたり)だとイマイチ分かりづらかったなあ。 上の例を思いついてればよかった。

cut相当の処理をするときのポイントは

である。上の展開を内側から見ていくとこんな感じ。

$(getent passwd user)             → user:*:1004:1003::/home/user:/bin/csh
${(@Ws,:,)$(getent passwd user)}  → user * 1004 1003 /home/user /bin/csh
"${(@Ws,:,)$(getent passwd user)}"→ user * 1004 1003  /home/user /bin/csh

2行目と3行目の違いは微妙だ。2行目は@フラグがダブルクォートに 入ってないので第5フィールドのnullフィールドが失われてしまっている。 3行目はnullフィールドが "" で入っている(見えないけどその周囲の空白 で分かる)。そしてそれを配列取り出しして

${"${(@Ws,:,)$(getent passwd user)}"[5]}

で完成。nullフィールドが見えなければ qq フラグ追加で確認。

echo ${"${(qq@Ws,:,)$(getent passwd user)}"[5]}
''
echo "${${(qq@Ws,:,)$(getent passwd user)}[5]}"
''

上記のようにダブルクォートは全体括りでもOK。

これまでシェルスクリプトでフィールド操作をするときは、 ポータビリティ重視でたいてい cut とか expr コマンドを使っていたが、 今回初めてzsh専用の本気スクリプトを作ったのでWフラグの意味を再確認。 ダブルクォート内の@と組み合わせないと説明分からんよなあ。