bash - mac - shell alias




创建一个带参数的Bash别名? (8)

我曾经使用CShell( csh ),它可以让你创建一个带参数的别名。 符号是类似的

alias junk="mv \\!* ~/.Trash"

在Bash中,这似乎不起作用。 鉴于Bash有许多有用的功能,我会假设这一个已经实现,但我想知道如何。


TL; DR:取而代之

使用函数比使用别名将参数置于命令中更容易且更易读。

$ wrap_args() { echo "before [email protected] after"; }
$ wrap_args 1 2 3
before 1 2 3 after

如果您继续阅读,您将了解到有关shell参数处理不需要了解的内容。 知识是危险的。 在黑暗的一面永远控制你的命运之前,只需得到你想要的结果。

澄清

bash别名确实接受参数,但只在最后

$ alias speak=echo
$ speak hello world
hello world

通过alias将参数置于命令的中间确实可能,但它变得很难看。

不要在家里尝试这个小子!

如果你喜欢绕过限制,做别人认为不可能的事情,这里就是食谱。 只要不要责怪我,如果你的头发变得疲惫不堪,你的脸就会变成烟尘疯狂的科学家风格。

解决方法是将alias仅在最后接受的参数传递给将它们插入中间然后执行命令的包装器。

解决方案1

如果你真的反对使用函数本身,你可以使用:

$ alias wrap_args='f(){ echo before "[email protected]" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after

如果您只想要第一个参数,您可以用$1替换[email protected]

说明1

这会创建一个临时函数f ,它传递参数(注意f在最后被调用)。 unset -f在别名被执行时删除函数定义,所以它不会在之后出现。

解决方案2

你也可以使用一个子shell:

$ alias wrap_args='sh -c '\''echo before "[email protected]" after'\'' _'

说明2

别名构建一个命令,如:

sh -c 'echo before "[email protected]" after' _

注释:

  • 占位符_是必需的,但它可以是任何东西。 它被设置为sh$0 ,并且是必需的,以便第一个用户给定的参数不会被消耗。 示范:

    sh -c 'echo Consumed: "$0" Printing: "[email protected]"' alcohol drunken babble
    Consumed: alcohol Printing: drunken babble
    
  • 单引号内的单引号是必需的。 下面是一个不使用双引号的例子:

    $ sh -c "echo Consumed: $0 Printing: [email protected]" alcohol drunken babble
    Consumed: -bash Printing:
    

    这里交互式shell的$0[email protected]的值传递给sh 之前被替换为双引号。 这是证明:

    echo "Consumed: $0 Printing: [email protected]"
    Consumed: -bash Printing:
    

    单引号确保这些变量不被交互式shell解释,并且被逐字传递给sh -c

    您可以使用双引号和\[email protected] ,但最好的做法是引用您的论点(因为它们可能包含空格),而\"\[email protected]\"看起来更丑陋,但可能会帮助您赢得模糊的头发是进入的先决条件。


Bash别名不直接接受参数。 你将不得不创建一个函数和别名。

alias不接受参数,但可以像调用别名一样调用函数。 例如:

myfunction() {
    #do things with parameters like $1 such as
    mv "$1" "$1.bak"
    cp "$2" "$1"
}


myFunction xyz #calls `myfunction`

顺便说一句,在.bashrc和其他文件中定义的Bash函数可以在您的shell中作为命令使用。 例如,你可以像这样调用早期的函数

$ myfunction original.conf my.conf

以下是我在~/.bashrc中的三个函数示例,它们本质上是接受参数的别名:

#Utility required by all below functions.
#https://.com/questions/369758/how-to-trim-whitespace-from-bash-variable#comment21953456_3232433
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"

:<<COMMENT
    Alias function for recursive deletion, with are-you-sure prompt.

    Example:
        srf /home/myusername/django_files/rest_tutorial/rest_venv/

    Parameter is required, and must be at least one non-whitespace character.

    Short description: Stored in SRF_DESC

    With the following setting, this is *not* added to the history:
        export HISTIGNORE="*rm -r*:srf *"
    - https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash

    See:
    - y/n prompt: https://.com/a/3232082/2736496
    - Alias w/param: https://.com/a/7131683/2736496
COMMENT
#SRF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
SRF_DESC="srf [path]: Recursive deletion, with y/n prompt\n"
srf()  {
    #Exit if no parameter is provided (if it's the empty string)
        param=$(echo "$1" | trim)
        echo "$param"
        if [ -z "$param" ]  #http://tldp.org/LDP/abs/html/comparison-ops.html
        then
          echo "Required parameter missing. Cancelled"; return
        fi

    #Actual line-breaks required in order to expand the variable.
    #- https://.com/a/4296147/2736496
    read -r -p "About to
    sudo rm -rf \"$param\"
Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        sudo rm -rf "$param"
    else
        echo "Cancelled."
    fi
}

:<<COMMENT
    Delete item from history based on its line number. No prompt.

    Short description: Stored in HX_DESC

    Examples
        hx 112
        hx 3

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HX_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HX_DESC="hx [linenum]: Delete history item at line number\n"
hx()  {
    history -d "$1"
}

:<<COMMENT
    Deletes all lines from the history that match a search string, with a
    prompt. The history file is then reloaded into memory.

    Short description: Stored in HXF_DESC

    Examples
        hxf "rm -rf"
        hxf ^source

    Parameter is required, and must be at least one non-whitespace character.

    With the following setting, this is *not* added to the history:
        export HISTIGNORE="*hxf *"
    - https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HXF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HXF_DESC="hxf [searchterm]: Delete all history items matching search term, with y/n prompt\n"
hxf()  {
    #Exit if no parameter is provided (if it's the empty string)
        param=$(echo "$1" | trim)
        echo "$param"
        if [ -z "$param" ]  #http://tldp.org/LDP/abs/html/comparison-ops.html
        then
          echo "Required parameter missing. Cancelled"; return
        fi

    read -r -p "About to delete all items from history that match \"$param\". Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        #Delete all matched items from the file, and duplicate it to a temp
        #location.
        grep -v "$param" "$HISTFILE" > /tmp/history

        #Clear all items in the current sessions history (in memory). This
        #empties out $HISTFILE.
        history -c

        #Overwrite the actual history file with the temp one.
        mv /tmp/history "$HISTFILE"

        #Now reload it.
        history -r "$HISTFILE"     #Alternative: exec bash
    else
        echo "Cancelled."
    fi
}

参考文献:


但是,在.bashrc文件中创建别名时不需要功能。 例如

# create an alias that takes port-number by the user
alias serve="python -m SimpleHTTPServer $1"

在.bashrc文件中进行更改后,确保输入以下命令。

~$ source .bashrc

你应该可以像这样使用它

~$ serve 8998

另一种解决方案是使用marker ,这是我最近创建的一个工具,它允许您为命令模板“添加书签”,并轻松地将光标放置在命令占位符处:

我发现大多数时候,我正在使用shell函数,所以我不必一次又一次地在命令行中编写经常使用的命令。 在这个用例中使用函数的问题是为我的命令词汇添加新的术语,并且必须记住参数在真实命令中引用的功能。 标记的目标是消除这种精神负担。


如果您正在寻找一种将所有参数应用于函数的通用方法,而不仅仅是一个或两个或其他硬编码数量,您可以这样做:

#!/usr/bin/env bash

# you would want to `source` this file, maybe in your .bash_profile?
function runjar_fn(){
    java -jar myjar.jar "[email protected]";
}

alias runjar=runjar_fn;

所以在上面的例子中,我将runjar运行到别名时的所有参数。

例如,如果我做runjar hi there它最终会实际运行java -jar myjar.jar hi there 。 如果我runjar one two three它会运行java -jar myjar.jar one two three

我喜欢这种基于[email protected]的解决方案,因为它适用于任何数量的参数。


注意:如果想法不明显,对别名使用别名是个坏主意,第一个是'别名中的函数',第二个是'难以读取的重定向/源'。 此外,还有一些缺陷(我认为这些缺陷很明显,但如果您感到困惑:我不认为它们实际上可以在任何地方使用!)

.................................................. .................................................. ............................................

我以前回答过这个问题,过去一直如此:

alias foo='__foo() { unset -f $0; echo "arg1 for foo=$1"; }; __foo()'

这很好,除非你一起避免使用函数。 在这种情况下,您可以利用bash的巨大能力重定向文本:

alias bar='cat <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'

他们都是相同的长度给或几个字符。

真正的踢球者是时差,顶端是'功能方法',底部是'重定向源'方法。 为了证明这个理论,时机本身就说明了这一点:

arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.004s sys 0m0.008s  # <--time spent in foo
 real 0m0.000s user 0m0.000s sys 0m0.000s  # <--time spent in bar
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.000s sys 0m0.012s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.012s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.008s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE

这是约200个结果的底部,以随机间隔完成。 看来,功能的创建/销毁需要比重定向更多的时间。 希望这会帮助未来的访问者解决这个问题(不想保留自己)。


这个问题只是被问到错误。 您不会创建一个使用参数的别名,因为alias只会为已存在的内容添加第二个名称。 OP需要的function是创建新功能的function命令。 由于该函数已具有名称,因此不需要别名该函数。

我想你想要这样的东西:

function trash() { mv "[email protected]" ~/.Trash; }

而已! 你可以使用参数$ 1,$ 2,$ 3等,或者只是用$ @





alias