Linux Bash-Zsh 快捷键模式 Emacs-Vim


原文链接: Linux Bash-Zsh 快捷键模式 Emacs-Vim

ZSH开发指南
zsh - Prompt Expansion
13 Prompt Expansion (zsh)

0=${(%):-%N}
%N The name of the script If there is none, this is equivalent to the parameter $0

source ${0:A:h}/zsh.d/.zplug.zsh
:A 等价于 readlink 读取原文件的地址
:h 字符串截取 目录

zsh compinit: insecure directories, run compaudit for list.

Ignore insecure directories and continue [y] or abort compinit [n]?
Hence, the solution implies fixing one (or all) of the following:

  1. setting the current user as the owner of all the directories/subdirectories/files in cause:
    compaudit | xargs chown -R "$(whoami)"
  2. removing write permissions for group/others for the files in cause:
    compaudit | xargs chmod go-w
  3. Another approach would be to skip these checks by using
    compinit -u

目录文件名截取

% filepath=/a/b/c.x
# :A 读取原文件的路径,等价于readlink

# :h 是取目录名,即最后一个 / 之前的部分,如果没有 / 则为 .
% echo ${filepath:h}
/a/b

# :t 是取文件名,即最后一个 / 之后的部分,如果没有 / 则为字符串本身
% echo ${filepath:t}
c.x

# :e 是取文件扩展名,即文件名中最后一个点之后的部分,如果没有点则为空
% echo ${filepath:e}
x

# :r 是去掉末尾扩展名的路径
% echo ${filepath:r}
/a/b/c

Bash 和 zsh 用法简明对照表

Bash 用法Zsh 用法说明
"$var"$var避免变量中有空格导致异常
"$@"$*避免变量中有空格导致异常
"${array[@]}"$array取数组所有元素,@ 可改成 *
"${#array[@]}"$#array取数组中元素个数,@ 可改成 *
"${array[n - 1]}"$array[n]取数组第 n 个元素,bash 从 0 开始,zsh 从 1 开始
"$array"$array[1]Bash 中的 $array 是取数组的第一个元素
echo a*becho "a*b"Zsh 默认配置中,通配符如果匹配不到文件会报错
if true; then :; fiif true {}Zsh 中不需要使用 : 作为空语句
[ "$var" == value ][[ $var == value ]]Zsh 中的 [ ] 里不支持 ==,一律用 [[ ]]
ls \| tee file \| lessls > file \| lessZsh 中不需要用 tee 即可实现相同功能

Bash 环境

多数时候我们用的是 Bash, 比如个人的 Linux 不愿去定制,远程服务器的由不得你去定制,所以就从 Bash 说起。
默认键绑定 emacs, 操作是 ctrl-x, ctrl-e

在默认的 Bash 环境下,只要在命令行中按下 ctrl-x, ctrl-e 就会把当前命令的内容调入到环境变量 $EDITOR 指示的编辑器(默认为 emacs)去编辑,编辑后保存退出就会立即执行。

如果未安装 Emacs 编辑器,在按下 ctrl-x, ctrl-e 会得到如下提示

[vagrant@localhost ~]$
-bash: emacs: command not found

如果希望使用 vi 来编辑当前命令,就需要设置 EDITOR 环境变量,比如在 .bashrc 中加入

export EDITOR=vi

那么在命令行中按下 ctrl-x, ctrl-e 使用打开 vi 来编辑当前命令。

注:Emacs 要用 ctrl-x, ctrl-c, 再回答 y, 命令保存到临时文中; 而 vi 的相应操作是 :wq, 至少这个操作上 vi 要简洁些。

可以用命令 bind -p | grep -F "\C-x\C-e 查看 ctrl-x, ctrl-e 是执行了 Readline 命令 edit-and-execute-command

$ bind -p | grep -F "\C-x\C-e"
"\C-x\C-e": edit-and-execute-command

更多:bind -p 可以显示所有的键绑定,bind -p | grep -F "\C" 可查看含 ctrl 按键的绑定。
键绑定为 vi 时,操作是正常模式下按 v 键

可以用命令 set -o vi 切换到 Vi 键绑定。切回到 emacs 键绑定用 set -o emacs。

Vi 键绑定时命令行就像是一个简单的行编辑器,Esc 在正常模式与输入模式间切换,如果要打开 Vi 来编辑当前命令只需在正常模式按下 v, 环境变量 $EDITOR 指定的编辑器(默认为 Vi ) 载入当前命令进行编辑。

如果对 Emacs 青睐有加的话,可以设置 $EDITOR 为 emacs, 这时按 v 键打开的就是 Emacs 编辑器。

Zsh 环境

快捷键设置

设置文件位置

绑定的设置可以写入 .zshrc 文件中。如果使用 oh-my-zsh ,配置还可以写入 ~/.oh-my-zsh/lib/key-bindings.zsh 中。

转换序列

在使用 bindkey 命令时,一帮第一个参数使用对应快捷键的 CSI 序列 ,如果想知道某种快捷组合键的 CSI 序列,可以有如下两种方法:

先按 Ctrl-V 然后再按组合键,如 Ctrl-A
输入 cat > /dev/null ,之后输入组合键

设置命令

前后移动一个单词

bindkey '^[^[[C' emacs-forward-word # Alt-Right
bindkey '^[^[[D' emacs-backward-word # Alt-Left
or
bindkey '^[Oc' emacs-forward-word # Ctrl-Right
bindkey '^[Od' emacs-backward-word # Ctrl-Left

同 Bash 的内置 bind 命令一样,Zsh 也有自己内置的键绑定命令 bindkey。而且也有相应的 emaces 和 vi 键绑定,切换的命令分别是 bindkey -e, 和 bindkey -v。

默认情况下,不管是 emacs 还是 vi 的按键绑定,ctrl-x, ctrl-e 和 v 键都不起作用,所以都得定制。针对两种键绑定类型分别为:

emacs 键绑定

默认的,或使用了 bindkey -e 指定为 emacs 键绑定,可以在 ~/.zshrc 中加入

autoload -z edit-command-line
zle -N edit-command-line
bindkey "^X^E" edit-command-line

source ~/.zshrc 后,便可按 ctrl-x, ctrl-e 打开 $EDITOR 指定的编辑器(默认为 vi) 来编辑当前命令

vi 键绑定

bindkey -v 切换键绑定到 vi, 在 ~/.zshrc 加入

autoload -z edit-command-line
zle -N edit-command-line
bindkey -M vicmd v edit-command-line

然后 source ~/.zshrc 后,在命令行的 vi 命令模式下按 v 键会打开$EDITOR 指定的编辑器(默认为 vi) 来编辑当前命令。

注意:在 Zsh 中,不管是 emacs 还是 vi 键绑定,未设置 $EDITOR 的话,默认都是 vi, 这一点与 Bash 是不同的。

bindkey 的几个相关命令:bindkey -l, bindkey -lL, bindkey -L, bindkey --, bindkey -a
总结

最好是设置环境变量 $EDITOR 明确指定编辑器是 emacs 还是 vi。
Bash emacs 键绑定按 ctrl-x, ctrl-e 打开编辑器载入命令,vi 键绑定按 v 键打开编辑器
Zsh 需要自行绑定按钮到 edit-command-line 命令
emacs  的保存退出命令是 ctrl-x, ctrl-c, 回答 y 退出,vi 就用 :wq 退出
配置只单单按v 键打开编辑器更容易产生误操作,也可能会与 vi 的可视模式混淆

任何情况下,不管是 Bash/Zsh, 无论何种键绑定都可以使用 fc 命令调用 EDITOR 来编辑最后一条执行的命令。

参考:

Vi mode in Bash
Zsh Line Editor
Zsh Zle Functions
Editing long commands in your shell
`