解析 zsh 命令行中的所有别名

WeS*_*ers 13 zsh alias

我有嵌套的别名,我想在执行命令之前解决所有这些问题。我怎么做?

如果有一个函数没有绑定到任何键,那么M-x foobar对我来说也很好。我什至可以使用外部命令(type, command, which, 等等)。我从线程中尝试了所有为什么不使用“which”?那用什么?但没有任何效果。

Sté*_*las 10

请注意,Ctrl-Alt-E inbash不仅扩展别名。它还扩展变量、命令替换 (!)、进程替换 (!)、算术扩展和删除引号(它不执行文件名生成(通配符)或波浪号扩展)。

它并不总是设法扩展别名。因此,尽管它有其用途,但重要的是要意识到其结果可能会改变命令行的含义,具有副作用并且具有潜在危险。

例如在:

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done
Run Code Online (Sandbox Code Playgroud)

如果我按M-C-E这里,那会给我:

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done
Run Code Online (Sandbox Code Playgroud)

这给了我一个完全不同的命令行(想象一下如果我有rm -rf *而不是pwd上面会发生什么)并且不会扩展foo别名。

使用zsh, 建立在 Gilles 关于在函数内部扩展的别名的注释,您可以执行以下操作:

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases
Run Code Online (Sandbox Code Playgroud)

仅当当前命令行在语法上有效时才会扩展别名(因此它兼作语法检查器)。

bash的 MCE相反,它还完全解析别名。例如,如果您有:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll
Run Code Online (Sandbox Code Playgroud)

将扩展为:

$ ls --color -l
Run Code Online (Sandbox Code Playgroud)

请注意,它还规范了语法,例如:

$ for i (*) cmd $i; foo
Run Code Online (Sandbox Code Playgroud)

将改为:

$ for i in *
        do
                cmd $i
        done
        foo
Run Code Online (Sandbox Code Playgroud)


Gil*_*il' 6

如果将命令行填充到函数定义中,然后打印出该函数,则别名将被扩展。您还将获得规范化的空格。

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}
Run Code Online (Sandbox Code Playgroud)

要将所有这些放入交互式命令中,您可以制作一个 zle 小部件。您可以通过将其代码填充到functions数组中的条目来直接定义函数;当你回读时,你会得到归一化的效果。

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey … normalize-command-line
Run Code Online (Sandbox Code Playgroud)

您在preexechook 中获得相同的归一化效果。自动加载函数时也会扩展别名(autoload -U通常用于避免别名扩展)。

_expand_alias如果它是一个别名,完成函数会扩展光标下的单词。它使用aliases数组。它不是递归的。您可以使用 实现更通用的别名扩展器aliases,但这有点困难,因为找出别名扩展的位置与 shell 语法密切相关。

  • 我总是使用 `autoload -U` 只是因为 zsh 文档推荐它,但直到我读到这个我才明白 `-U` 实际做了什么:)。同样对于任何感兴趣的人,可以通过在命令行中输入别名直接调用 [_expand_alias](http://zsh.sourceforge.net/Doc/Release/Completion-System.html#index-_005fexpand_005falias) 函数,点击` &lt;Esc&gt;`,`x`,启动小缓冲区,然后输入`_expand_alias&lt;Enter&gt;` (2认同)