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

Hel*_*llo 1164 bash alias

我以前使用CShell(),它允许你创建一个带参数的别名.符号是这样的

alias junk="mv \\!* ~/.Trash"
Run Code Online (Sandbox Code Playgroud)

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

aru*_*mar 1973

Bash别名不直接接受参数.您必须创建一个函数和别名.

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

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


myfunction old.conf new.conf #calls `myfunction`
Run Code Online (Sandbox Code Playgroud)

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

$ myfunction original.conf my.conf
Run Code Online (Sandbox Code Playgroud)

  • 您甚至不必声明别名.只需定义该功能即可. (253认同)
  • 如果要将别名更改为函数,则`source`ing .bashrc将添加该函数,但它不会为旧别名添加unalias.由于别名比函数更高,它将尝试使用别名.您需要关闭并重新打开shell,否则调用`unalias <name>`.也许我会在5分钟内拯救一个人,我只是浪费了. (187认同)
  • @MartinNeal:我在Sun学到的一个节省时间的技巧就是做一个`exec bash`:它会启动一个新的shell,给你一个干净的读取你的配置,就好像你关闭并重新打开,但保持那个会话的环境变量设置.此外,当你想要像堆栈一样处理思考时,执行没有exec的`bash`会很有用. (54认同)
  • 我应该在报价中包装`$ 1`吗? (42认同)
  • @mich - 是的,总是把bash变量放在引号中.例如`mv"$ 1""$ 1.bak"`.没有引号,如果1美元是"你好世界",你将执行`mv hello world hello world.bak`而不是`mv"hello world""hello world.bak"`. (19认同)
  • 谢谢!我喜欢它.这允许我创建一个别名来转换我的mac上的perl的dos2unix.`my_d2u(){tr -d'\ r'<$ 1> $ 2} alias dos2unix = my_d2u; 别名d2u = my_d2u;` (4认同)
  • 如果你把它放在 `~/.bashrc` 或类似的东西里,函数名必须加上 `function`。例如`function myfunc{echo $1}` (4认同)
  • 函数是持久存在还是只能用于shell会话的范围?如果是后者,你怎么能坚持下去? (2认同)
  • @raven你在"〜/ .bashrc"中写它们以使它们持久化. (2认同)

Mik*_*son 196

改进上面的答案,您可以像使用别名一样获得单行语法,这对于shell或.bashrc文件中的ad-hoc定义更方便:

bash$ myfunction() { mv "$1" "$1.bak" && cp -i "$2" "$1"; }

bash$ myfunction original.conf my.conf
Run Code Online (Sandbox Code Playgroud)

不要忘记关闭右括号前的分号.同样,对于实际问题:

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

bash$ junk() { mv "$@" ~/.Trash/; }
Run Code Online (Sandbox Code Playgroud)

要么:

bash$ junk() { for item in "$@" ; do echo "Trashing: $item" ; mv "$item" ~/.Trash/; done; }
Run Code Online (Sandbox Code Playgroud)

  • 改变`mv"$ 1""$ 1.bak"; cp"$ 2""$ 1"`进入`mv"$ 1""$ 1.bak"&& cp"$ 2""$ 1"`当`mv`遇到麻烦时(例如,文件系统已满)不丢失数据. (14认同)
  • 我更喜欢这个答案,因为它显示了迭代可能出现的参数数组.$ 1和$ 2只是特殊情况,这也在这个答案中说明. (3认同)
  • "不要忘记关闭右括号前的分号." 很多次这个!谢谢 :) (3认同)
  • 并且第一个括号之后和最后一个括号之前的空格也是必需的。 (2认同)

Eva*_*ois 110

这个问题简直被问到了错误.您不创建带参数的别名,因为alias只为已存在的内容添加第二个名称.OP想要的功能是function创建新功能的命令.您不需要为函数设置别名,因为函数已有名称.

我想你想要这样的东西:

function trash() { mv "$@" ~/.Trash; }
Run Code Online (Sandbox Code Playgroud)

而已!您可以使用参数$ 1,$ 2,$ 3等,或者只需将它们全部填入$ @

  • 这个答案说明了一切.如果我从本页底部读到,我会节省一些时间. (7认同)
  • @FuzzyLogic - 我花了几分钟尝试解压您评论中的代码。将一些代码打包到无法正确格式化的注释中需要花费大量(有趣的)努力。我仍然没有弄清楚它到底是做什么的,或者更重要的是,为什么它支持你的(正确的)断言。 (2认同)
  • “问错了”?这假设 OP 知道*确切*该问什么,如果他/她知道了,他们很可能一开始就不会问。这是一个提问的论坛,希望能清楚地提出问题,但我们不要在这里过分评判。 (2认同)

Tom*_*ale 97

TL; DR:改为做

使用函数比使用别名将参数放在命令中间更容易,更易读.

$ wrap_args() { echo "before $@ after"; }
$ wrap_args 1 2 3
before 1 2 3 after
Run Code Online (Sandbox Code Playgroud)

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

澄清

bash别名确实接受参数,但仅限于结尾:

$ alias speak=echo
$ speak hello world
hello world
Run Code Online (Sandbox Code Playgroud)

将参数置于命令通过的中间alias确实是可能的,但它变得丑陋.

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

如果您喜欢规避限制并做其他人认为不可能的事情,那么这就是配方.如果你的头发被弄得疲惫不堪,你的脸最终会被煤烟疯狂科学家风格覆盖,请不要怪我.

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

解决方案1

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

$ alias wrap_args='f(){ echo before "$@" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after
Run Code Online (Sandbox Code Playgroud)

如果您只想要第一个参数$@,$1则可以替换为.

解释1

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

解决方案2

您还可以使用子shell:

$ alias wrap_args='sh -c '\''echo before "$@" after'\'' _'
Run Code Online (Sandbox Code Playgroud)

解释2

别名构建如下命令:

sh -c 'echo before "$@" after' _
Run Code Online (Sandbox Code Playgroud)

评论:

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

    sh -c 'echo Consumed: "$0" Printing: "$@"' alcohol drunken babble
    Consumed: alcohol Printing: drunken babble
    
    Run Code Online (Sandbox Code Playgroud)
  • 单引号内的单引号是必需的.这是一个不使用双引号的例子:

    $ sh -c "echo Consumed: $0 Printing: $@" alcohol drunken babble
    Consumed: -bash Printing:
    
    Run Code Online (Sandbox Code Playgroud)

    这里的交互shell的值$0$@被替换成引述双前,它被传递给sh.这是证据:

    echo "Consumed: $0 Printing: $@"
    Consumed: -bash Printing:
    
    Run Code Online (Sandbox Code Playgroud)

    单引号确保这些变量不被交互式shell解释,并按字面顺序传递给sh -c.

    您可以使用双引号\$@,但最佳做法是引用您的参数(因为它们可能包含空格),\"\$@\"看起来更加丑陋,但可能会帮助您赢得混淆比赛,其中疲惫的头发是进入的先决条件.

  • 对于解决方案1,请确保使用单引号,并避免在$ @附近使用\“。如果需要,这是一种非常有用的技术。 (2认同)

Ami*_*sef 36

另一种解决方案是使用marker,这是我最近创建的一个工具,它允许您"命名"命令模板并轻松将光标放在命令占位符上:

命令行标记

我发现大部分时间,我都在使用shell函数,因此我不必在命令行中反复编写常用命令.在这个用例中使用函数的问题是在命令词汇表中添加新术语,并且必须记住在real-command中引用的函数参数.标记的目标是消除这种心理负担.


Iva*_*van 26

一旦我做了一些有趣的项目,我仍然在使用它。当我通过cp命令复制文件时,它显示了一些动画,cp因为没有显示任何内容,这有点令人沮丧。所以我做了这个别名

alias cp="~/SCR/spiner cp"
Run Code Online (Sandbox Code Playgroud)

这是微调脚本

#!/bin/bash

#Set timer
T=$(date +%s)

#Add some color
. ~/SCR/color

#Animation sprites
sprite=( "(* )  ( *)" " (* )( *) " " ( *)(* ) " "( *)  (* )" "(* )  ( *)" )

#Print empty line and hide cursor
printf "\n${COF}"

#Exit function
function bye { printf "${CON}"; [ -e /proc/$pid ] && kill -9 $pid; exit; }; trap bye INT

#Run our command and get its pid
"$@" & pid=$!

#Waiting animation
i=0; while [ -e /proc/$pid ]; do sleep 0.1

    printf "\r${GRN}Please wait... ${YLW}${sprite[$i]}${DEF}"
    ((i++)); [[ $i = ${#sprite[@]} ]] && i=0

done

#Print time and exit
T=$(($(date +%s)-$T))
printf "\n\nTime taken: $(date -u -d @${T} +'%T')\n"

bye
Run Code Online (Sandbox Code Playgroud)

它看起来像这样

在此处输入图片说明

循环动画)

在此处输入图片说明

这是上面提到的颜色脚本的链接。和新的动画循环)

在此处输入图片说明

  • 这是无价的。 (7认同)

Bil*_*leh 17

Bash 别名绝对接受参数。我刚刚添加了一个别名来创建一个新的 React 应用程序,它接受应用程序名称作为参数。这是我的过程:

在 nano 中打开 bash_profile 进行编辑

nano /.bash_profile
Run Code Online (Sandbox Code Playgroud)

添加别名,每行一个:

alias gita='git add .'
alias gitc='git commit -m "$@"'
alias gitpom='git push origin master'
alias creact='npx create-react-app "$@"'
Run Code Online (Sandbox Code Playgroud)

注意:“$@”接受传入的参数,如“creact my-new-app”

保存并退出纳米编辑器

ctrl+o 写入(按回车键);ctrl+x 退出

告诉终端使用 .bash_profile 中的新别名

source /.bash_profile
Run Code Online (Sandbox Code Playgroud)

就是这样!您现在可以使用新别名

  • 如果参数位于命令中间,这似乎不起作用。我怀疑发生的事情是您正在调用别名,后跟“参数”,而“参数”恰好位于命令的末尾,因此它被解释为好像最后的参数位于末尾。例如 `gitc foo` 运行 `git commit -m foo` 不是因为你有一个 $@ 而是因为 foo 出现在最后——它正在运行 `git commit -m` 并且你碰巧有一个紧随其后的 `foo`附加,这使你的命令有效。 (4认同)
  • 总而言之,别名接受参数,但仅当放在别名末尾时才接受。这是一种有限的参数。并且您不需要在别名定义中使用`$@`。 (3认同)

小智 13

尊重所有那些说你不能在别名中间插入参数的人,我刚刚测试了它并发现它确实有效。

alias mycommand = "python3 "$1" script.py --folderoutput RESULTS/"
Run Code Online (Sandbox Code Playgroud)

然后,当我运行 mycommand foobar 时,它的工作方式与我手写命令时完全一样。

  • “没有像 csh 中那样在替换文本中使用参数的机制” https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Aliases 您的命令可能有效,因为 *appending*无论您在该命令行末尾输入 $1 ,仍然适用于您正在做的任何事情。 (4认同)
  • 对我不起作用: ```alias myalias="echo 1 "$1" 3"; myalias 2```` 给我:````1 3 2```` (3认同)
  • 其工作方式与:`alias mycommand = "python3 script.py --folderoutput RESULTS/"`(省略`"$1"`)相同。这是一样的,因为 alias 不会在 bash 中设置位置参数。在交互式 shell 中,它们的值为 "" 一个空字符串,除非您在其中放置了一些内容。为了进一步测试这一点,请尝试在定义别名之前向 $1 添加一些内容:`set -- Something`。现在您的别名很可能已损坏,请查看该别名包含的内容:`alias mycommand` (2认同)

ali*_*ind 10

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

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

.

:<<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://stackoverflow.com/a/3232082/2736496
    - Alias w/param: https://stackoverflow.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://stackoverflow.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
}
Run Code Online (Sandbox Code Playgroud)

.

:<<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"
}
Run Code Online (Sandbox Code Playgroud)

.

:<<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
}
Run Code Online (Sandbox Code Playgroud)

参考文献:

  • 不,它的功能与功能完全相同.就像这里解释的几个答案一样,你不能创建一个带参数的别名.你能做的就是写一个函数,这就是你所做的. (2认同)
  • 这里有一些非常好的例子,以及很好的评论代码.对于访问此页面的人们来说是一个很大的帮助. (2认同)

Ken*_*ran 7

您要做的就是在别名中创建一个函数:

$ alias mkcd='function _mkcd(){mkdir "$1"; cd "$1"}; _mkcd'
Run Code Online (Sandbox Code Playgroud)

必须在“ $ 1”周围加上双引号,因为单引号将不起作用。

  • 这很聪明,但是除了问题确实指定要创建别名这一事实之外,是否有理由不仅仅使函数的名称最初与别名相同? (4认同)
  • @xaxxon 不是真的,但这是我知道使用别名而不是函数的最简单方法。 (2认同)
  • 我已经解决了语法问题。回复:删除“function”前缀,请参阅 https://wiki.bash-hackers.org/scripting/obsolete 中的讨论。也就是说,我不知道为什么有人会这样做而不是只定义一个函数而不使用任何别名。 (2认同)

Wil*_*ens 7

我将发布我的(希望是好的)解决方案(对于未来的读者,最重要的是编辑)。
所以 - 请编辑和改进/删除这篇文章中的任何内容。

在终端中:

$ alias <name_of_your_alias>_$argname="<command> $argname"
Run Code Online (Sandbox Code Playgroud)

并使用它(注意“_”后面的空格:

$<name_of_your_alias>_ $argname
Run Code Online (Sandbox Code Playgroud)

例如,名为以下cat文件的别名hello.txt

  • (别名是CAT_FILE_
  • $f(是$argname,在本例中是一个文件)
$ alias CAT_FILE_$f="cat $f"

$ echo " " >> hello.txt
$ echo "hello there!" >> hello.txt
$ echo " " >> hello.txt
$ cat hello.txt

    hello there!
Run Code Online (Sandbox Code Playgroud)

测试(注意“_”后面的空格):

CAT_FILE_ hello.txt
Run Code Online (Sandbox Code Playgroud)

  • 这是可行的,但出于完全不同的原因。它起作用只是因为“$f”位于末尾。`$f` 在别名定义时可能为空,因此解析为 `alias CAT_FILE_="cat "`。只需运行“alias”即可查看生成的定义。因此,当您调用“CAT_FILE_”时,您只需将参数传递给别名,就像“alias ll =“ls -l””中的任何其他别名用法一样。尝试将“参数”“$f”放在末尾以外的其他位置,这是行不通的。例如:`alias ECHO_ARG_$f="echo xxx $f yyy"`。然后`ECHO_ARG_ test`导致`xxx yyy test`。 (6认同)

osi*_*hra 6

注意:如果想法不明显,除了别名之外的任何东西都使用别名是个坏主意,第一个是"别名中的函数",第二个是"难以读取的重定向/源".此外,还有一些缺陷(我认为这很明显,但万一你会感到困惑:我并不是说它们实际上被用到了......任何地方!)

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

我之前已经回答了这个问题,过去一直如此:

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

这是好的和好的,除非你一直避免使用功能.在这种情况下,您可以利用bash的重定向文本的巨大能力:

alias bar='cat <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'
Run Code Online (Sandbox Code Playgroud)

它们的长度大约相同或者取一些字符.

真正起脚的时间差,顶部作为"函数法"和底部作为"重定向源"的方法.为证明这一理论,时机不言而喻:

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
ubuntu@localhost /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
ubuntu@localhost /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
ubuntu@localhost /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
ubuntu@localhost /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
Run Code Online (Sandbox Code Playgroud)

这是大约200个结果的底部,以随机间隔完成.似乎函数创建/销毁比重定向花费更多时间.希望这将有助于未来的访问者提出这个问题(不想保留给自己).

  • 拥有一个定义函数的别名,然后运行该函数真是愚蠢。只需编写一个函数。对于几乎所有目的,别名都被shell函数取代。 (2认同)
  • 嘿,我从来没有说过做任何这个都是好主意,我只是说还有其他方法可以解决它 - 这里的主要想法是你不应该在别名中使用函数,因为它们比复杂的更慢重定向,我想这本来是显而易见的,但我想我必须为每个人拼出来(如果我这样做的话,我也会因为帖子过于臃肿而大喊大叫) (2认同)

Mic*_*cah 5

如果您正在寻找一种将所有参数应用于一个函数的通用方法,而不仅仅是一个或两个或一些其他硬编码量,则可以通过以下方式实现:

#!/usr/bin/env bash

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

alias runjar=runjar_fn;
Run Code Online (Sandbox Code Playgroud)

因此,在上面的示例中,我将运行时的所有参数传递runjar给别名。

例如,如果我这样做runjar hi there,它将最终真正运行java -jar myjar.jar hi there。如果我这样做runjar one two three,它将运行java -jar myjar.jar one two three

我喜欢这种$@基于解决方案的方法,因为它适用于任意数量的参数。

  • 为什么不只是命名函数`runjar`而不是使其成为函数的别名呢?似乎不必要的复杂! (3认同)
  • 这是没有意义的。与`alias runjar ='java -jar myjar.jar'`相同。别名确实接受参数,但只能在最后。 (3认同)

cro*_*bc1 5

有合法的技术原因需要一个通用的解决方案来解决 bash 别名没有采取重新定位任意参数的机制的问题。一个原因是,如果您希望执行的命令会因执行函数而导致的环境变化受到不利影响。在所有其他情况下,应使用函数。

最近促使我尝试解决此问题的原因是我想创建一些用于打印变量和函数定义的缩写命令。所以我为此编写了一些函数。但是,某些变量会(或可能会)被函数调用本身改变。其中有:

FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV

我一直在使用(在函数中)打印变量 defns 的基本命令。在 set 命令输出的表单中是:

sv () { set | grep --color=never -- "^$1=.*"; }
Run Code Online (Sandbox Code Playgroud)

例如:

> V=voodoo
sv V
V=voodoo
Run Code Online (Sandbox Code Playgroud)

问题:这不会打印上述变量的定义,因为它们在当前上下文中,例如,如果在交互式 shell 提示中(或不在任何函数调用中),则未定义 FUNCNAME。但是我的函数告诉我错误的信息:

> sv FUNCNAME
FUNCNAME=([0]="sv")
Run Code Online (Sandbox Code Playgroud)

我想出的一个解决方案已被其他人在有关此主题的其他帖子中提到。对于这个打印变量 defns. 的特定命令,它只需要一个参数,我这样做了:

alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'
Run Code Online (Sandbox Code Playgroud)

这给出了正确的输出(无)和结果状态(假):

> asv FUNCNAME
> echo $?
1
Run Code Online (Sandbox Code Playgroud)

但是,我仍然觉得有必要找到一种适用于任意数量参数的解决方案。

将任意参数传递给 Bash 别名命令的通用解决方案:

# (I put this code in a file "alias-arg.sh"):

# cmd [arg1 ...] – an experimental command that optionally takes args,
# which are printed as "cmd(arg1 ...)"
#
# Also sets global variable "CMD_DONE" to "true".
#
cmd () { echo "cmd($@)"; declare -g CMD_DONE=true; }

# Now set up an alias "ac2" that passes to cmd two arguments placed
# after the alias, but passes them to cmd with their order reversed:
#
# ac2 cmd_arg2 cmd_arg1 – calls "cmd" as: "cmd cmd_arg1 cmd_arg2"
#
alias ac2='
    # Set up cmd to be execed after f() finishes:
    #
    trap '\''cmd "${CMD_ARGV[1]}" "${CMD_ARGV[0]}"'\'' SIGUSR1;
    #        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    #       (^This is the actually execed command^)
    #
    # f [arg0 arg1 ...] – acquires args and sets up trap to run cmd:
    f () {
        declare -ag CMD_ARGV=("$@");  # array to give args to cmd
        kill -SIGUSR1 $$;             # this causes cmd to be run
        trap SIGUSR1;                 # unset the trap for SIGUSR1
        unset CMD_ARGV;               # clean up env...
        unset f;                      # incl. this function!
    };
    f'  # Finally, exec f, which will receive the args following "ac2".
Run Code Online (Sandbox Code Playgroud)

例如:

> . alias-arg.sh
> ac2 one two
cmd(two one)
>
> # Check to see that command run via trap affects this environment:
> asv CMD_DONE
CMD_DONE=true
Run Code Online (Sandbox Code Playgroud)

这个解决方案的一个好处是,用于处理命令的位置参数(参数)的所有特殊技巧在编写被捕获的命令时都将起作用。唯一的区别是必须使用数组语法。

例如,

如果您想要“$@”,请使用“${CMD_ARGV[@]}”。

如果您想要“$#”,请使用“${#CMD_ARGV[@]}”。

等等。


小智 5

要对有关创建别名以将文件移动到垃圾箱文件夹而不是删除它们的问题给出具体答案:

alias rm="mv "$1" -t ~/.Trash/"
Run Code Online (Sandbox Code Playgroud)

当然,您必须先创建 dir ~/.Trash 。

然后只需给出以下命令:

$rm <filename>
$rm <dirname>
Run Code Online (Sandbox Code Playgroud)

  • 或者甚至更好并且具有相同的结果: `alias rm="mv "$i_bellieve_this_is_ Correct_because_it_WORKS" -t ~/.Trash/"` 仍然不相信的可以在之前运行此命令: `set -- my_very_important_file` 按字面意思运行它或使用如果您确信别名中的 $1 有效,则指向您非常重要的文件的路径。现在声明: `alias rm="mv "$1" -t ~/.Trash/"` 和 `rm &lt;filename&gt;` 按照建议。`set --` 将值设置为位置参数 $1。别名命令没有。 (4认同)

小智 5

句法:

alias shortName="your custom command here"
Run Code Online (Sandbox Code Playgroud)

例子:

alias tlogs='_t_logs() { tail -f ../path/$1/to/project/logs.txt ;}; _t_logs'
Run Code Online (Sandbox Code Playgroud)

  • 为什么要这样做而不是仅仅定义一个函数并且根本没有任何别名? (3认同)

小智 5

使用子命令的解决方案:

d () {
    if [ $# -eq 0 ] ; then
        docker
        return 0
    fi
    CMD=$1
    shift

    case $CMD in
    p)
        docker ps --all $@
        ;;
    r)
        docker run --interactive --tty $@
        ;;
    rma)
        docker container prune
        docker image prune --filter "dangling=true"
        ;;
    *)
        docker $CMD $@
        ;;
    esac
    return $?
}
Run Code Online (Sandbox Code Playgroud)

使用:

$ d r my_image ...
Run Code Online (Sandbox Code Playgroud)

称为:

docker run --interactive --tty my_image ...
Run Code Online (Sandbox Code Playgroud)


Spa*_*arr 5

您可以在别名中创建匿名函数:

alias mkcd='(){mkdir "$1";cd "$1";}'
Run Code Online (Sandbox Code Playgroud)

您需要"周围$1来处理其中包含空格的名称。外部避免了转义和'的需要。您还可以将 all与一堆转义一起使用:"$"

alias mkcd="(){mkdir \"\$1\";cd \"\$1\";}"
Run Code Online (Sandbox Code Playgroud)

我认为这比创建命名函数的多个其他答案更清晰。

其中任何一个都有相同的用法。随后mkcd foomkdir "foo"cd "foo"