如何访问函数内调用者的命令行参数?
Posted
技术标签:
【中文标题】如何访问函数内调用者的命令行参数?【英文标题】:How to access command line arguments of the caller inside a function? 【发布时间】:2011-02-14 00:23:48 【问题描述】:我正在尝试在 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 $*
【问题讨论】:
我有点困惑,你想要 args 而不传递它们? 是的,关键是从函数内部获取命令行参数,而不将它们作为函数参数传递。它与错误处理情况有关,在这种情况下,我想根据命令行参数进行错误处理,而与传递给函数的参数无关。 仅供参考,$*
非常有问题——它会将./yourScript "first argument" "second argument"
更改为./yourscript "first" "argument" "second" "argument"
,或者将./yourscript '*.txt'
更改为./yourscript one.txt two.txt
之类的东西,尽管有引号。
【参考方案1】:
#!/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 $#
编辑:请参阅我对问题的评论
【讨论】:
【参考方案2】:如果您想使用 C 风格的参数(参数数组 + 参数数量),您可以使用 $@
和 $#
。
$#
为您提供参数的数量。$@
为您提供所有参数。你可以通过args=("$@")
把它变成一个数组。
例如:
args=("$@")
echo $# arguments passed
echo $args[0] $args[1] $args[2]
请注意,这里的$args[0]
实际上是第一个参数,而不是脚本的名称。
【讨论】:
这并没有解决这个问题——它是在询问将命令行参数传递给一个 shell 函数。 @Jefromi,实际上,它完美地回答了这个问题。你可以在函数内部使用args
数组,前提是你事先按照描述对其进行了初始化。
我发现这比遍历 args 要干净得多。
这个简单易行。很好的答案。您在 7 多年前发布了此内容,因此您好,来自未来:2017 年 7 月
更好的是引用echo "$args[0] $args[1] $args[2]"
,或者参数受文件名扩展的影响。【参考方案3】:
# 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
【讨论】:
【参考方案4】:Ravi 的评论基本上就是答案。函数有自己的参数。如果您希望它们与命令行参数相同,则必须将它们传入。否则,您显然是在调用不带参数的函数。
也就是说,如果您愿意将命令行参数存储在全局数组中以在其他函数中使用,则可以:
my_function()
echo "stored arguments:"
for arg in "$commandline_args[@]"; do
echo " $arg"
done
commandline_args=("$@")
my_function
您必须通过commandline_args
变量而不是$@
、$1
、$2
等来访问命令行参数,但它们是可用的。我不知道有什么方法可以直接分配给参数数组,但是如果有人知道,请赐教!
另外,请注意我使用和引用 $@
的方式 - 这样可以确保特殊字符(空格)不会被混淆。
【讨论】:
【参考方案5】:我对@987654321@ 的阅读说这些东西被捕获在BASH_ARGV 中, 尽管它经常谈论“堆栈”。
#!/bin/bash
shopt -s extdebug
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
fbaz bar boo arg2 arg1 arg0
g goo gar gaz
ggaz gar goo arg2 arg1 arg0
f
fgaz gar goo arg2 arg1 arg0
【讨论】:
请注意,像这样迭代数组会导致参数与命令行的顺序相反。$BASH_ARGV[*]
应该是"$BASH_ARGV[@]"
带双引号和@
【参考方案6】:
您可以使用 shift 关键字(运算符?)来遍历它们。 示例:
#!/bin/bash
function print()
while [ $# -gt 0 ]
do
echo "$1"
shift 1
done
print "$@"
【讨论】:
function print()
是两种不同的函数声明形式之间的混合体——function print
,这是 bash 支持向后兼容 pre-POSIX(也就是说,1991 年之前)的遗留 ksh 语法) ksh 和print()
,这是 POSIX 标准化的。考虑使用一种或另一种来与其他 shell 更广泛地兼容;另见wiki.bash-hackers.org/scripting/obsolete【参考方案7】:
这样也可以
#!/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 支持向后兼容 pre-POSIX(也就是说,1991 年之前)的遗留 ksh 语法) ksh 和print()
,这是 POSIX 标准化的。考虑使用一种或另一种来与其他 shell 更广泛地兼容;另见wiki.bash-hackers.org/scripting/obsolete【参考方案8】:
我是这样做的:
#! /bin/bash
ORIGARGS="$@"
function init()
ORIGOPT= "- $ORIGARGS -" # tacs are for sed -E
echo "$ORIGOPT"
【讨论】:
【参考方案9】:将参数从命令行传递到特定函数的最简单且可能最好的方法是将参数直接包含在函数调用中。
# first you define your function
function func_ImportantPrints()
printf '%s\n' "$1"
printf '%s\n' "$2"
printf '%s\n' "$3"
# then when you make your function call you do this:
func_ImportantPrints "$@"
无论您是将参数发送到 main 还是某些函数(如 func_parseArguments(如前面示例中所示包含 case 语句的函数)或脚本中的任何函数),这都很有用。
【讨论】:
【参考方案10】:这是包含多个 cmets 的 @mcarifio 响应:
#!/bin/bash
shopt -s extdebug
function stuff()
local argIndex="$#BASH_ARGV[@]"
while [[ argIndex -gt 0 ]] ; do
argIndex=$((argIndex - 1))
echo -n "$BASH_ARGV[$argIndex] "
done
echo
stuff
我想强调一下:
shopt -s extdebug
很重要。如果没有这个 BASH_ARGV
数组将是空的,除非您在脚本的 top level 部分使用它(这意味着在 stuff
函数之外)。详情在这里:Why does the variable BASH_ARGV have a different value in a function, depending on whether it is used before calling the function
BASH_ARGV
是一个堆栈,因此参数以倒序存储在那里。这就是为什么我减少循环内的索引以便我们以正确的顺序获得参数的原因。
需要将$BASH_ARGV[@]
和@
作为索引而不是*
周围的双引号,以便正确处理带有空格的参数。详情在这里:bash arrays - what is difference between $#array_name[*] and $#array_name[@]
【讨论】:
以上是关于如何访问函数内调用者的命令行参数?的主要内容,如果未能解决你的问题,请参考以下文章