@znz blog

ZnZ の memo のようなもの

zshでgrepのようなことをする

| Comments

zsh で簡易 grep 的なことができたので、紹介します。

実行例

${name:#pattern}(M) フラグを組み合わせると配列から glob pattern にマッチしたものだけ抜き出せます。

1
2
3
4
% echo ${(FM)${(f)"$(< /etc/hosts)"}:#*local*}
127.0.0.1       localhost
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet

(M) フラグなしだと grep -v のようにマッチしなかったものだけが残ります。

1
2
3
% echo ${(F)${(f)"$(< /etc/passwd)"}:#*:[1-8]*}
root:x:0:0:root:/root:/bin/bash
news:x:9:9:news:/var/spool/news:/bin/sh

解説

  1. まず最初に $(< filename) でファイルから内容を読み込んでいます。
  2. 次に "" で改行などの IFS に含まれる空白による分割を抑制しています。
  3. そして ${(f)var}f フラグは ps:\n: の省略形で、改行で分割して配列にするという意味です。ここまでの処理は zsh での典型的な処理なので覚えておくと便利です。
  4. その次がメインの ${name:#pattern} です。指定するパターンは正規表現ではなくファイル glob のパタ ーンのようです。 (M) フラグと組み合わせることでマッチしなかった要素を削除しています。
  5. 最後に ${(F)var}F フラグは pj:\n: の省略形で、改行で結合するという意味です。

F フラグは M フラグと同時に指定しても問題なかったので、括弧 (${} の方) をネストさせずに同じ所 に書いています。 f フラグは別にしないとうまく動きませんでした。

行全体とのマッチなので、前後に * をつけないと一部に含むという意味になりません。 逆に後ろだけに * をつけて行頭マッチなどが出来るということでもあります。

Comments