• home
  • about
  • 全ての投稿
  • ソフトウェア・ハードウェアの設定のまとめ
  • 分析関連のまとめ
  • ヘルスケア関連のまとめ
  • 生涯学習関連のまとめ

zsh

date: 2021-02-06 excerpt: zshのtips

tag: zshshell


zshのtips

インストール

osx

$ brew install zsh

デフォルトのshellをzshにする

$ chsh -s $(which zsh)
  • rootユーザでこの変更を行うのはrootでログインできなくなる可能性があり、リスクである

プラグインで機能を拡張する

antigen

  • 依存が少ないプラグインマネージャ

インストール

$ curl -L git.io/antigen > antigen
$ source ~/antigen # .zshrcの中で読み込む

プラグインのインストール

antigen bundle <plugin-name>

zsh-autosuggestions

  • hisotryの中から同じ文字で始まるコマンドと引数をレコメンドしてくれる

インストール

antigen bundle zsh-users/zsh-autosuggestions

必要に応じてbitbucketに.zshrcを更新して管理する

  • link

キーバインド

デフォルトのよく使う設定

  • "^[^?": backward-kill-word
    • alt + deleteでカーソルの後ろのワードを削除(argumentの一つを消す)

設定されたキーバインドを確認する

$ bindkey

特定の機能をバインドする

# Alt+wで次の単語へ
bindkey "∑" forward-word
# Alt+bで前の単語へ
bindkey "∫" backward-word
# Alt+→で次の単語へ
bindkey "^[[1;3C" forward-word
# Alt+←で次の単語へ
bindkey "^[[1;3D" backward-word
# Alt+aでautosuggest-accept
bindkey "å" autosuggest-accept
  • alt + arrowで前か次の単語へ移動できる

zshの構文と具体例

ヒアドキュメントでzshを動かす

$ zsh -f

複数のコマンドの実行

;

  • 左のコマンドが正常に実行できてもできなくても右のコマンドを実行

&&

  • 左のコマンドが正常に実行できた時、右のコマンドを実行する

||

  • 左のコマンドが正常に実行できない時、右のコマンドを実行する

シングルクオートとダブルクオートの違い

  • シングルクオート
    • シェル変数を内部で展開しない
  • ダブルクオート
    • シェル変数を内部で展開する

インターネット上にあるzshスクリプトを読み込む

ダウンロード場所を指定しておき、存在しなれけば読み込む

# gistによる機能拡張
function load_remote_zshrc() {
  # 1. .tmpが存在しなかったら作成
  # 2. .tmp/zshrcが存在しなかったらダウンロード
  if [[ ! -d ~/.tmp ]]; then
        echo "create local .tmp directry."
        mkdir ~/.tmp
  fi
  if [[ ! -f ~/.tmp/zshrc ]]; then
        echo "create local .tmp directry."
        curl -o ~/.tmp/zshrc https://gist.githubusercontent.com/GINK03/e96cf8fa45a5c97846d5b6cb362d5ce7/raw/zshrc
  fi
  source ~/.tmp/zshrc
}
load_remote_zshrc

関数を定義して呼び出す

# 定義
# rf <filename>
function rf {
  # 必須な引数
  readonly file_name=${1:?"rgで検索するファイル名の引数"}
  rg --files | rg $file_name # ラップしたコマンド
}
# 呼び出し
rf "hoge"

if文

if [[ "$PARAM" = "master" ]]; then
  echo "これはmaster"
elif [[ "$PARAM" = "main" ]]; then
  echo "これはmain"
else
  echo "これはFalse"
fi
  • 必ず、[[のあとにはspace一個、]]の前にspace一個が必要

ディレクトリがあるかどうかのチェック

if [[ -d ~/.tmp ]]; then
  echo "存在する"
else
  echo "存在しない"
fi

ファイルがあるかどうかのチェック

if [[ -f ~/target_file ]]; then
  echo "存在する"
else
  echo "存在しない"
fi

シンボリックリンクがあるかどうかのチェック

if [[ -L ~/.zshrc ]]; then
  echo "存在する"
else
  echo "存在しない"
fi

特定のコマンドが存在するかのチェック

この例ではlsb_releaseが存在するかの確認
whichではaliasが設定されているときは正しくハンドルされないので、typeのほうが汎用性がある

if type "lsb_release" > /dev/null; then
  echo "存在する"
fi

for文

for bin in peco vim nvim tmux
do
  echo $bin
done
  • peco, vim, nvim, tmuxがそれぞれ改行されて出力される
names=("山田" "田中" "斎藤")
for name in ${names[@]}; do
  echo $name
done

"""
山田
田中
斎藤
"""

case文

例えばOSで処理を分けるとき

case `uname` in
  Darwin)
    echo "MacOSX"
  ;;
  Linux)
    echo "Linux"
esac

プログラムの異常終了をキャッチする

$ echo $?
1
  • 0のとき正常
  • 1のとき異常
  • その他のとき何らかのソフトウェアごとに予約された動作

stringをsplitしてリストにする

# spaceで分割する
string="aaa bbb ccc ddd"
parts=(${(@s: :)string})
echo $parts[2] # bbbが出力
parts=(${(@s/ /)string})
echo $parts[2] # bbbが出力
  • この記法はzshでしか動作しない(bash, shはエラー)

コマンドを実行する直前のhook、直後のhook

autoload -Uz add-zsh-hook
preexec_any_function () {
  # コマンドを実行する前の関数
}
precmd_any_function () {
  # コマンドを実行後の関数
}
# hookに関数を登録
add-zsh-hook preexec preexec_any_function
add-zsh-hook precmd  precmd_any_function

pythonでコマンドを作る

  1. .zshrcにpythonスクリプトを記入して変数に代入する
  2. インラインのpythonの引数に変数を与えたものにエイリアスを張る
export my_python_command_script='
import os

for arg in sys.argv[1:]:
    print(f"{arg}という引数が入力されました")
'
alias my_python_command="python3 -c '$my_python_command_script'"

terminalにgitのbranchを表示する

zshにはvcs_infoというモジュールが存在し、gitのbranchを取得できる
precmd関数はコマンドを打つ前に自動で走るコマンドで、この中に記すことで、コマンド度に最新のbranch情報に更新できる

autoload -U colors && colors
autoload -Uz vcs_info
zstyle ':vcs_info:*' enable git svn
zstyle ':vcs_info:git*' formats "%b"
function precmd() {
  vcs_info
  PS1="%{$fg[cyan]%}%n@%m%{$reset_color%}:%1 %~ (${vcs_info_msg_0_})$ "
}
setopt prompt_subst

terminalにdatetimeを表示する

PS1のフォーマットは以下のようになる

%D{ %Y-%m-%d %M:%H:%S}

terminalを改行する

PS1に直接\nを書けないので、以下のように変数を作って代替する

NEWLINE=$'\n'
PS1="hogehoge ${NEWLINE} foobar"

aliasの実体を確認する

$ type -a n
n is an alias for nvim
...

aliasを解除する

sudo, ipなどをラップしていると不整合を起こすことがあるのでそのような場合に使える

$ unalias sudo

rootユーザになる

環境によって方法が異なる

$ sudo su

または

$ sudo -s

トラブルシューティング

環境変数を適切に設定しているのに、lsコマンド等で文字化けが起きるとき

  • 原因
    • 何らかの影響でlocalesパッケージが不整合を起こしていることがあった
  • 対応
    • 以下のコマンドでja_JP.UTF-8に設定し直すことで治った事があった
$ sudo dpkg-reconfigure locales

終端文字%が正しくハンドルされなくて描画がずれる時

  • 原因
    • zshの機能の1つで終端文字をstdinがキャッチできないとき、%で代替する機能があり、ハンドルにミスるとterminalが崩壊する
  • 対応
    • resetを入力する
$ reset
  • 参考

ctrl+a, ctrl+eでzshで移動できない(^A, ^Eが入力されてしまう)

  • 原因
    • ctrl+a, ctrl+eがハンドルされていない
  • 対応
    • .zshrcと.tmux.confでemacsスタイルを適応すると入力できる

.zshrc

bindkey -e

.tmux.conf

set -g mode-keys emacs
set -g status-keys emacs
  • 参考

sudoしたときユーザ定義のaliasを引き継ぐ

alias sudo="sudo "
  • 参考

zsh compinit: insecure directories...と警告がでる

  • 原因
    • zshのモジュールがセキュアな設定になっていないことが原因
    • brewのzsh補完などが原因ででることがある
  • 対応
    • compauditで出力される内容を、ユーザonlyのパーミッションにすることで修正することができる
$ compaudit | xargs chmod g-w
  • 参考


zshshell Share Tweet