Bash 函数,发生了奇怪的事情!

Bash 函数,发生了奇怪的事情!

我是 bash 函数的新手,但刚刚开始编写一些零散的内容来加快我的工作流程。我喜欢在进行过程中对此进行测试,所以我发现自己经常编辑和获取我的 ~/.profile 并发现~/.打字有点尴尬......

所以我想我要做的第一件事如下:

sourceProfile(){
    source ~/.profile
}

editProfile(){
    vim ~/.profile && sourceProfile
}

运行 editProfile 时,我在 sourceProfile 调用上遇到问题。最初我收到错误:

-bash: ~./profile: No such file or directory

请注意我的函数中没有拼写错误!

但是,如果我使用别名,它就会起作用。

alias sourceProfile='source ~/.profile'

但是,在添加该别名然后将其注释掉并取消注释该函数后,我开始收到语法错误:

-bash: /home/jonathanramsden/.profile: line 45: syntax error near unexpected token `('
-bash: /home/jonathanramsden/.profile: line 45: `sourceProfile(){'

行是:

alias sservice='sudo service'

我很确定我所做的只是评论/取消评论!根据我的谷歌搜索,这似乎是定义函数的语法。

答案1

别名就像某种形式的宏扩展,类似于 C 中的预处理,#define只是在 shell 中,预处理阶段和解释阶段之间没有清晰可见的界限(而且,别名不会在所有上下文中扩展)并且可以有几轮别名扩展,就像嵌套别名一样)。

当你这样做时:

alias sourceProfile='source ~/.profile'
sourceProfile() {
  something
}

别名扩展将其变成:

source ~/.profile() {
  something
}

这是一个语法错误。和:

alias sourceProfile='source ~/.profile'
editProfile(){
  vim ~/.profile && sourceProfile
}

将其变成:

editProfile(){
  vim ~/.profile && source ~/.profile
}

所以,如果你以后重新定义sourceProfile为函数,editProfile就不会调用它,因为 的定义editProfile具有原始别名的扩展值。

此外,对于函数(或任何复合命令),别名仅在函数定义时间(当它们被读取和解析时),而不是在运行时。所以这:

editProfile(){
  vim ~/.profile && sourceProfile
}
alias sourceProfile='source ~/.profile'
editProfile

不起作用,因为sourceProfile在解析函数体时尚未定义editProfile,并且在运行函数时不会有任何别名扩展editProfile

因此,避免混合别名和函数。并警惕使用别名的影响,因为它们并不是真正的命令而是某种形式的宏观扩张。

答案2

当开发测试函数时,请确保在source每次编辑之间重新加载 () 函数定义,否则旧的函数定义仍将处于活动状态。您的函数中没有拼写错误,并且您不应该收到该错误消息(我无法在此处重现它),这意味着您没有按照编写的方式运行该函数。

另外,我建议您开始使用$HOME而不是~在编写脚本时使用,主要是因为~它的行为根本不像变量(请参阅为什么波形符 (~) 不在双引号内展开?)。


建议:

edit_profile () {
    local EDITOR=${EDITOR:-vim}
    local file="$HOME/.profile"

    "$EDITOR" "$file" && source "$file"
}

file变量是额外的,但该EDITOR变量可能已设置为合理的编辑器。如果不是,代码将其设置为vim

相关内容