如何在函数内访问调用方的命令行参数?


95

我试图用bash编写一个函数,该函数将访问脚本的命令行参数,但是将其替换为该函数的位置参数。如果未显式传递命令行参数,该函数是否可以访问命令行参数?

# Demo function
function stuff {
  echo $0 $*
}

# Echo's the name of the script, but no command line arguments
stuff

# Echo's everything I want, but trying to avoid
stuff $*

3
我有点困惑,您想让参数不通过它们吗?
拉维·维亚斯

4
是的,重点是从函数内部获取命令行参数,而不将其作为函数参数传递。它与错误处理情况有关,在这种情况下,我想基于命令行参数进行错误处理,而与传递给函数的参数无关。
DonGar 2010年

仅供参考,$*它非常容易出错- 尽管有引号,但它将更改./yourScript "first argument" "second argument"./yourscript "first" "argument" "second" "argument"或更改./yourscript '*.txt'为类似内容./yourscript one.txt two.txt
查尔斯·达菲

Answers:


46

我对bash ref手册的阅读说,尽管很多时候都在谈论“堆栈”,但是BASH_ARGV中捕获了这些东西。

#!/bin/bash

function argv {
    for a in ${BASH_ARGV[*]} ; do
      echo -n "$a "
    done
    echo
}

function f {
    echo f $1 $2 $3
    echo -n f ; argv
}

function g {
    echo g $1 $2 $3
    echo -n g; argv
    f
}

f boo bar baz
g goo gar gaz

保存在f.sh中

$ ./f.sh arg0 arg1 arg2
f boo bar baz
farg2 arg1 arg0 
g goo gar gaz
garg2 arg1 arg0 
f
farg2 arg1 arg0 

5
请注意,对数组进行类似的操作会导致args从命令行以相反的顺序进行。
安德鲁·贝克

93

如果要使用C风格的参数(参数数组+参数数量),可以使用$@$#

$#给你参数的数量。
$@给你所有的论点。您可以通过将其转换为数组args=("$@")

因此,例如:

args=("$@")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}

请注意,这里${args[0]}实际上是第一个参数,而不是脚本的名称。


5
这没有解决问题-它询问是否将命令行参数传递给Shell函数。
卡斯卡贝尔

6
@Jefromi,实际上,它完美地回答了这个问题。args如果事先按照说明进行了初始化,则可以从函数内部使用数组。
vadipp

1
我发现这比遍历args更干净。
费利克斯·加侬-格雷尼尔

1
这很简单。好答案。您在7年前发布了此信息,以便将来向您问好:2017
SDsolar

更好的方法是引用like echo "${args[0]} ${args[1]} ${args[2]}",否则参数会受到文件名扩展的影响。
本杰明·

17
#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#

编辑:请参阅我对问题的评论


16

拉维的评论实质上就是答案。函数采用自己的参数。如果希望它们与命令行参数相同,则必须传递它们。否则,您显然是在调用不带参数的函数。

就是说,您可以将命令行参数存储在全局数组中,以在其他函数中使用:

my_function() {
    echo "stored arguments:"
    for arg in "${commandline_args[@]}"; do
        echo "    $arg"
    done
}

commandline_args=("$@")

my_function

你必须通过访问命令行参数commandline_args变量,而不是$@$1$2等,但他们提供。我不知道直接分配给参数数组的任何方法,但是如果有人知道,请赐教!

另外,请注意我使用和引用的方式$@-这是确保不混淆特殊字符(空格)的方式。


6
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*

function stuff {
  # use script args via the variables you saved
  # or the function args via $
  echo $0 $*
} 


# Call the function with arguments
stuff 1 2 3 4

2

一个人也可以这样做

#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $@;do
    echo $i
done;
}
argument $@

现在像这样调用您的脚本

./function_test.sh argument1 argument2

function print() {是两种不同的函数声明形式之间的一种混合形式- function print {,这是bash支持与POSIX之前(即1991年前)的ksh向后兼容的旧式ksh语法,以及print() {是POSIX标准化的。考虑使用一个或另一个以与其他外壳更广泛的兼容性;另请参阅wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

您可以使用shift关键字(operator?)遍历它们。例:

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo $1;
        shift 1;
    done
}
print $*;

2
function print() {是两种不同的函数声明形式之间的一种混合形式- function print {,这是bash支持与POSIX之前(即1991年前)的ksh向后兼容的旧式ksh语法,以及print() {是POSIX标准化的。考虑使用一个或另一个以与其他外壳更广泛的兼容性;另请参见wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

我的解决方案:

创建一个比所有其他函数更早调用的函数脚本,而不向其传递任何参数,如下所示:

!/ bin / bash

函数init(){ORIGOPT =“-$ @-”}

之后,您可以调用init并根据需要使用ORIGOPT var,此外,我总是分配一个新的var并在我的新函数中复制ORIGOPT的内容,这样您就可以确保没有人会碰它或更改。

我添加了空格和破折号以使其更易于使用'sed -E'进行解析,而且bash不会将其作为引用传递,并且随着函数被更多的参数调用而使ORIGOPT增长。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.