假设我已经执行了一个命令
foo a b c d e f
然后我可以用来$!
访问该命令的最后一个参数,即如果我输入
echo !$
它变成了echo f
。同样我可以使用
echo !:4
访问第 4 个元素,d
但这意味着我必须从左边数。有没有从右边访问第 n 个元素的符号?
假设我已经执行了一个命令
foo a b c d e f
然后我可以用来$!
访问该命令的最后一个参数,即如果我输入
echo !$
它变成了echo f
。同样我可以使用
echo !:4
访问第 4 个元素,d
但这意味着我必须从左边数。有没有从右边访问第 n 个元素的符号?
我必须在 zsh 中为命令设置值自动完成(在下面的最小示例中,我将使用 进行展示testcmd
)。因此,我当前的代码可以很好地处理硬编码值:
function testcmd()
{
echo "Nothing to do, just a test command"
}
_test_complete() {
_values \
"Possible values" \
foo'[Foo]' \
bar'[Bar baz]' \
}
compdef _test_complete testcmd
当我输入时testcmd <tab>
,我正确地得到了以下所需的渲染:
$ testcmd
Possible values
bar -- Bar baz
foo -- Foo
但是正如您所看到的,这些值在函数内部是硬编码的,理想情况下,函数应该从变量中检索它们。
因此很自然地,我将值放入变量中,values_variable
如下所示:
function testcmd()
{
echo "Nothing to do, just a test command"
}
_test_complete() {
local values_variable
values_variable="foo'[Foo]' \
bar'[Bar baz]' \ "
_values \
"Possible values" \
${values_variable}
}
compdef _test_complete testcmd
但是当我尝试时testcmd <tab>
它完全失败了:
$ testcmd
_values:compvalues:11: invalid value definition: foo'[Foo]' \t\tbar'[Bar baz]' \
_values:compvalues:11: invalid value definition: foo'[Foo]' \t\tbar'[Bar baz]' \
_values:compvalues:11: invalid value definition: foo'[Foo]' \t\tbar'[Bar baz]' \
$ testcmd
echo ${values_variable} | sed "s/ /\\ /g"
;$values_variable
命令eval
来假装它的内容直接在定义中输入_values
;eval
并逃脱eval $(echo ${values_variable} | sed "s/ /\\ /g")
;echo "$values_variable" | while read -r line; do
eval "$line"
done
${(@f)values_variable}̀
;在 如何使用to (zsh 补全) tread传递文件内容cat
_values
中,我找到了从外部文件导入值的解决方案,但用户似乎面临着相同的空格转义问题。但是,我无法将其调整为内部变量的情况$values_variables
。
我自然尝试了这个,但它也不起作用:
_test_complete() {
local values_variable
values_variable="foo'[Foo]' \
bar'[Bar baz]' \ "
OLD_IFS=$IFS
IFS=$'\n'
_values \
"Possible values" \
${values_variable}
IFS=$OLD_IFS
}
_values
如何从变量加载要提供给自动完成函数内部的值?
function tail() {
shift 1
echo $@
}
% tail one two three
two three
我怎样才能写出这个简单函数的反函数?
我想实现
% init one two three
one two
并获取变量中除最后一个参数之外的所有参数$@
,因此该函数可以写成
function init() {
# ???
echo $@
}
我已经尝试过unset '@[-1]'
,,unset '[@:-1]'
来自https://unix.stackexchange.com/a/611717/696135,但这些不起作用
我已经尝试过set -- "${@:1:$(($#-1))}"
,,来自https://stackoverflow.com/questions/20398499/remove-last-argument-from-argument-list-of-shell-script-bashunset "@[${#@[@]}-1]"
,但这些不起作用set -- "${@:1:$#-1}"
不起作用的脚本示例:
function init() {
set -- ${@:1:$#-1}
echo $@
}
init one two three
以下脚本非递归地删除常规空文件(不包括点文件),然后非递归地删除空目录(不包括点文件),并忽略.DS_Store
文件的存在(也就是说,如果目录只包含一个.DS_Store
文件,那么该目录仍然会被删除)。
rm -f -- *(.L0)
setopt extended_glob
has_files_other_than_DS_Store() [[ -n $REPLY/^(#i).ds_store(#qNDY1) ]]
remove_empty_macos_dirs() {
local dir ret=0
for dir do
rm -f -- $dir/.(#i)ds_store(N.) && rmdir -- $dir || ret=$?
done
return $ret
}
remove_empty_macos_dirs *(/^+has_files_other_than_DS_Store)
有人能演示如何使其递归工作吗?也就是说,第一步是递归删除所有空的常规文件。然后递归删除空目录。
我会自己尝试,但说实话,我只是害怕尝试这个rm
命令。
我一直在按照本指南https://thevaluable.dev/zsh-install-configure-mouseless/来设置我的 autocmp 。我在 MacOS 环境中,但由于某种原因,当我尝试自动完成选项时,它没有列出完整的选项集。这是我的自动完成配置:
#Completion
autoload -Uz compinit
compinit
zmodload zsh/complist
#Amazing article https://thevaluable.dev/zsh-install-configure-mouseless/
zstyle ':completion:*' completer _extensions _complete _approximate
zstyle ':completion:*' menu select
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:*:*:*:descriptions' format '%F{green}-- %d --%f'
zstyle ':completion:*' complete-options true
zstyle ':completion:*' matcher-list 'r:|=*' 'l:|=* r:|=*' #https://unix.stackexchange.com/a/259511
zstyle ':completion:*' verbose yes
zstyle ':completion:*' group-name ''
zstyle ':completion:*' list-colors 'di=34:fi=31:no=33;00'
# zstyle ':completion:*' file-list all #Unfortunetly this messes up colouring
#Move with VIM keys Autocompletion
bindkey '^[[Z' reverse-menu-complete
bindkey -M menuselect 'h' vi-backward-char
bindkey -M menuselect 'k' vi-up-line-or-history
bindkey -M menuselect 'l' vi-forward-char
bindkey -M menuselect 'j' vi-down-line-or-history
当我尝试自动完成内置 shell 命令的选项时,我得到以下信息:
❯ cp -
-- option --
-H -- follow symlinks on the command line in recursive mode
-L -- follow all symlinks in recursive mode
-P -- do not follow symlinks in recursive mode (default)
-R -- copy directories recursively
-X -- don\'t copy extended attributes or resource forks
-a -- archive mode, same as -RpP
-f -- force overwriting existing file
-i -- confirm before overwriting existing file
-n -- don\'t overwrite existing file
-p -- preserve timestamps, mode, owner, flags, ACLs, and extended attributes
-v -- show file names as they are copied
我希望获得cp
文章中的完整选项列表。这可能是 MacOs 中 zsh 补全的问题吗?
我有这个 zsh 函数:
f() {
/usr/bin/find . -type f | less
}
当我运行此函数时,使用 Ctrl+z 暂停,然后运行 fg,它显示zsh: suspended (tty output) /usr/bin/find . -type f |
并且我无法恢复。这是为什么?我该如何恢复?
arch% f
zsh: suspended /usr/bin/find . -type f |
arch% fg
[2] - continued /usr/bin/find . -type f |
zsh: suspended (tty output) /usr/bin/find . -type f |
zsh: suspended (tty output) /usr/bin/find . -type f |
arch%
如果我/usr/bin/find . -type f | less
直接从命令行运行而不将其作为函数,它将正常暂停和恢复。
我的登录 shell 是 zsh。我在文件中添加了以下两行.zprofile
:
path+=$HOME/foobar123
alias foo='echo bar'
bash
然后,如果我通过键入或fish
并按回车键切换到 bash 或 fish ,echo $PATH
将继续显示该foobar123
部分,但foo
别名不起作用。
这是为什么?为什么别名和路径修改的处理方式不同?
我大多数时候更喜欢在 macOS 上使用 fish shell,但不要将其用作登录 shell,因为我认为有时它可能会导致问题。
exec fish
因此,我只需在 的最底部添加.zshrc
,就完成了。这意味着我的登录 shell 仍然是 zsh,我的$PATH
修改仍然在 中.zprofile
,但是当我打开终端时,我不必手动切换到 fish。对我来说很完美。
但是,如果我出于某些特定原因仍然想从 fish 切换到 zsh 怎么办? 有可能吗?(因为如果我简单地输入zsh
并按回车键,我当然会立即切换回 fish。)
更新:有一个解决方法zsh -c
,但它只适用于某些命令。
我有一个精心创建的.zshrc
,我不想在其中添加任何未手动添加的内容。是否有可能某些程序、安装程序或命令会自动在其中添加一些行?(即在最开始还是在最结尾?)
换句话说,我确实明白echo foo > ~/.zshrc
会对其进行修改,但还有其他类似的情况吗?