如何将传递给我的 bash 脚本的所有参数传递给我的函数? [复制]

Posted

技术标签:

【中文标题】如何将传递给我的 bash 脚本的所有参数传递给我的函数? [复制]【英文标题】:How to pass all arguments passed to my bash script to a function of mine? [duplicate] 【发布时间】:2011-04-18 04:51:07 【问题描述】:

假设我定义了一个function abc(),它将处理与分析传递给我的脚本的参数相关的逻辑。

如何将我的 bash 脚本收到的所有参数传递给它?参数的数量是可变的,所以我不能像这样硬编码传递的参数:

abc $1 $2 $3 $4

编辑。更好的是,我的函数有什么方法可以访问脚本参数的变量吗?

【问题讨论】:

Propagate all arguments in a bash shell script 的可能重复项。 (这个问题实际上是在此处链接的问题之前发布的。但链接中的问题具有更详细的答案和更丰富的标题,可能最好作为参考问题) 【参考方案1】:

$@ 变量扩展为所有由空格分隔的命令行参数。这是一个例子。

abc "$@"

在使用$@ 时,您应该(几乎)始终将其放在双引号中以避免错误解析包含空格或通配符的参数(见下文)。这适用于多个参数。它还可以移植到所有符合 POSIX 标准的 shell。

另外值得注意的是$0(一般是脚本的名称或路径)不在$@中。

Bash Reference Manual Special Parameters Section 表示$@ 扩展为从一开始的位置参数。当扩展出现在双引号内时,每个参数都扩展为一个单独的单词。即"$@" 等价于"$1" "$2" "$3"...

传递一些参数:

如果您想传递除第一个以外的所有参数,您可以首先使用shift 来“使用”第一个参数,然后传递"$@" 以将剩余的参数传递给另一个命令。在 bash(以及 zsh 和 ksh,但不是在像 dash 这样的普通 POSIX shell 中)中,您可以使用数组切片的变体来执行此操作而不会弄乱参数列表:"$@:3" 将为您提供以 "$3" 开头的参数。如果传递了那么多参数,"$@:3:4" 将为您提供从 "$3" 开始的最多四个参数(即"$3" "$4" "$5" "$6")。

你可能不想做的事情:

"$*" 将所有参数组合成一个字符串(由空格分隔,或者$IFS 的第一个字符是什么)。这失去了空格 within 参数和空格 between 参数之间的区别,因此通常是一个坏主意。尽管打印参数可能没问题,例如echo "$*",前提是您不关心保留区别内/之间的空间。

将参数分配给常规变量(如args="$@")会像"$*" 那样将所有参数混合在一起。如果要将参数存储在变量中,请使用带有args=("$@") 的数组(括号使其成为数组),然后将它们引用为例如"$args[0]" 等请注意,在 bash 和 ksh 中,数组索引从 0 开始,因此 $1 将在 args[0] 等中。另一方面,zsh 从 1 开始数组索引,因此 $1 将是在args[1]。像 dash 这样更基本的 shell 根本没有数组。

省略双引号,使用$@$*,将尝试将每个参数拆分为单独的单词(基于空格或$IFS 中的任何内容),并尝试扩展任何看起来就像文件名通配符到匹配文件名列表中一样。这可能会产生非常奇怪的影响,并且几乎应该始终避免。 (除了在 zsh 中,默认情况下不会发生这种扩展。)

【讨论】:

阅读更多关于为什么在此处使用双 " 很重要:***.com/a/4824637/4575793 "$@:3" 似乎不适用于zsh 额外注释:$* 将是一个字符串,IFS 的第一个字符是连接元素。 @kvantour 如果$* 用双引号括起来,就会发生这种情况。如果它没有被引用,它会受到分词和通配符扩展的影响,因此它会立即重新拆分回元素 并且 任何包含 $IFS 字符的元素也将被拆分(然后任何通配符都会被拆分)展开)。最终结果:没有双引号,$*$@ 最终给出相同的结果。 @DylanYoung 您必须解析它们以确定哪些应该被视为选项参数。例如,在somecmd -a b c -d 中,-a 显然是一个选项,但b-a 的一个参数(因此是它的“一部分”),还是一个简单的位置参数?你需要知道-a 是否需要一个参数来决定。此外,如果 - 在第一个位置命令之前,某些命令仅将其识别为指示选项,因此 -d 可能是也可能不是选项,具体取决于此命令使用的策略。【参考方案2】:

我需要对此进行修改,希望对其他人有用:

function diffs() 
        diff "$@:3" <(sort "$1") <(sort "$2")

"$@:3" 部分表示从 3 开始的数组的所有成员。所以这个函数通过将前两个参数通过 sort 传递给 diff,然后将所有其他参数传递给 diff 来实现排序的 diff,所以你可以调用它类似于 diff:

diffs file1 file2 [other diff args, e.g. -y]

【讨论】:

"$@:3" 在您的脚本有参数时也很棒,但也可以将参数传递给它们调用的其他脚本。例如,我的一个项目有一个用于轻松运行程序的脚本,并带有一个供主类使用的参数。然后"$@:2" 可用于将剩余的参数传递给该入口点。 @Kat 已经提到了这一点,但要澄清一下(以防您仍有疑问):command "$@" 等同于command $1 "$@:2" 天啊!我你!【参考方案3】:

使用$@ 变量,该变量扩展为所有由空格分隔的命令行参数。

abc "$@"

【讨论】:

【参考方案4】:

这是一个简单的脚本:

#!/bin/bash

args=("$@")

echo Number of arguments: $#
echo 1st argument: $args[0]
echo 2nd argument: $args[1]

$# 是脚本接收的参数数量。我发现使用数组更容易访问它们:args=("$@") 行将所有参数放在args 数组中。要访问它们,请使用$args[index]

【讨论】:

第一个参数是$args[0] :o 将 $@ 传递到数组中比仅按索引调用参数(例如,$1)有什么好处? 投票同意与@King 的协议,即第一个元素需要在 [0] 处作为数组。 不知何故我错过了它。已修复,谢谢指出。 未来的读者应该注意这个例子中的shebang是不正确的。 sh 不支持数组,这是一个 bash 功能。这可能起作用的唯一原因是,如果您的操作系统已将 /bin/sh 符号链接到 bash,或者您使用 bash script.sh 调用脚本。【参考方案5】:

值得一提的是,您可以使用此语法指定参数范围。

function example() 
    echo "line1 $@:1:1"; #First argument
    echo "line2 $@:2:1"; #Second argument
    echo "line3 $@:3"; #Third argument onwards

我没看到有人提到过。

【讨论】:

前两个可以使用$1, $2,... @rubo77 我已经更正了答案的措辞,包括“范围”谢谢。 谢谢,这正是我用变量索引$@ 所需要的【参考方案6】:

abc "$@" 通常是正确的答案。 但是我试图将参数传递给 su 命令,并且没有多少引用可以阻止错误su: unrecognized option '--myoption'。实际上对我有用的是将所有参数作为单个字符串传递:

abc "$*"

我的确切情况(我确定其他人需要这个)在我的 .bashrc 中

# run all aws commands as Jenkins user
aws ()

    sudo su jenkins -c "aws $*"

【讨论】:

嘿,OP,看起来你在 abc 示例中可能有错字 正是我需要的。我的命令用引号括起来,这是唯一对我有用的东西。 大概是这样的使用方式,但要注意使用字符串参数时的风险。请在此处查看“$*”示例:***.com/a/46205560/4575793(更多关于 '$@' 与 '$*' 以及引用的变体)【参考方案7】:
abc "$@"

$@ 表示为您的 bash 脚本提供的所有参数。

【讨论】:

如果不引用$@会丢失正确的分词 @Daenyth 是对的,请在此处阅读更多信息:***.com/a/4824637/4575793

以上是关于如何将传递给我的 bash 脚本的所有参数传递给我的函数? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Linux 中使用终端命令将文件参数传递给我的 bash 脚本? [复制]

如何将文件参数传递给我的 bash 脚本两次并修改文件名

如何将强制和可选命令行参数传递给 perl 脚本?

如何通过 nginx 将路径参数传递给 lua 代码?

如何将文件路径作为 bash 脚本中的参数传递给函数? [复制]

执行 curl 获取的脚本时将参数传递给 bash