如何在Bash中更改命令行参数?

118

有没有一种方法可以在Bash脚本中更改命令行参数?例如,一个Bash脚本被调用如下:

./foo arg1 arg2  

有没有一种方法可以在脚本内改变arg1的值?类似于:

$1="chintz"
4个回答

184

您需要重置所有的参数。例如修改参数$3:

$ set -- "${@:1:2}" "new_arg3" "${@:4}"

基本上,您可以将set 所有 参数设置为它们当前的值,除了您想要更改的参数。 set --POSIX 7 中也被指定。

"${@:1:2}"表示法 被扩展为从偏移量1(即$1)开始的两个位置参数(因此在符号中有2)。 在这种情况下,它是"$1" "$2"的简写,但是当您想替换例如"${17}"时,它会更加有用。


1
那么,为了改变$3,我必须同时改变$1和$2,是吗?改成什么?"重置"是什么意思? - Sriram
谢谢你的技巧!我在使用内嵌空格的文件名时遇到了困难。如果其他人也遇到了这个问题,可以尝试按照这里的建议,在行开头加上 eval - cxw
2
当您知道要更改的参数位置时,这是可以的。如果您实际上不知道它并且需要动态更改它呢?我尝试使用$ set -- "${:1:$pivot}",但它不接受变量。 - Daniele Segato
1
我该如何在函数内部执行相同的操作?当从函数内调用时,您的解决方案似乎无效。 - Hashken
3
在函数内部无法更改脚本的位置参数,因为函数的自有参数会覆盖它们。但是,您可以将它们存储在数组中并对其进行操作。 - thkala
我需要一些额外的帮助来理解这个答案,所以我在这里写了一个解释性更全面的答案。感谢你的工作让我有了一个开始。 - Gabriel Staples

26

为了提高可读性和可维护性,您最好将$1$2分配给更有意义的变量(比如说input_filename = $1output_filename = $2之类的),然后重写其中一个变量(input_filename = 'chintz'),以保留脚本中的输入不变,以防在其他地方需要使用。


我想要一种方法,可以直接修改其中一个输入参数本身。我需要这样做是因为我想从脚本中返回一个值。thkala提出的答案很有效。谢谢你的回复! - Sriram
3
同意。为了易读性,你的方法更好。 - Dss
1
“你最好”这句话的意义取决于具体的使用情境,而这个情境并没有被提供。 - Him
2
@Scott比我写这个答案时多了7年的经验和年龄,我倾向于同意你的观点。 - johnsyweb
以下是一个不适用的例子(除非使用类似$FIRST_PARAMETER这样的东西):参数的使用和含义取决于实际值。 - Igor Stoppa
@Sriram,我无法想象在什么情况下你不能传递变量的值,然后从脚本中返回它。您介意澄清一下这个答案不起作用的情况吗? - BUFU

9

我知道这是一篇老的文章,但我发现thkala的答案非常有用,因此我借鉴了这个想法并稍微扩展了一下,使我能够为任何未定义的参数添加默认值-例如:


    # set defaults for the passed arguments (if any) if not defined.
    #
    arg1=${1:-"default-for-arg-1"}
    arg2=${2:-"default-for-arg-2"}
    set -- "${arg1}" "${arg2}"
    unset arg1 arg2

我希望这对其他人有用。


3

如何使用set --在bash中更改命令行参数$1$2

作为对Ask Ubuntu上@Radu Rădeanu的主要答案Stack Overflow上@thkala的主要答案的补充,我想添加一个非常简单的示例,以一次设置多个参数,如下所示:

# set arguments `$1`, `$2`, and `$3` to these respective values
set -- "one" "two" "three"
echo "$1 $2 $3"

输出:

one two three

如果您想要更改参数后还有其他参数,您可以通过将它们切片到末尾来保留它们,就像这样:
set -- "one" "two" "three" "${@:4}"

我在这里的回答中解释了"${@:4}"切片语法:Unix & Linux: Bash: slice of positional parameters。请参阅该答案以获取有关bash数组切片的更多详细信息。以下是其中的一小段代码:
# array slicing basic format 1: grab a certain length starting at a certain
# index
echo "${@:2:5}"
#         │ │
#         │ └────> slice length
#         └──────> slice starting index 

# array slicing basic format 2: grab all remaining array elements starting at a
# certain index through to the end
echo "${@:2}"
#         │
#         │
#         └──────> slice starting index 
所以,在@thkala的主要答案中,包括了这个内容:
set -- "${@:1:2}" "new_arg3" "${@:4}"

...解释是"${@:1:2}"获取前两个参数,"new_arg3"将其作为新的第三个参数插入,而"${@:4}"从第4个参数到最后一个参数获取所有参数,从而仅更改参数3并保持所有其他参数不变。

要获取有关内置bash命令set的帮助,请参阅help set或在此处在线查看:https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#The-Set-Builtin

help set显示--参数的以下内容:

 --  Assign any remaining arguments to the positional parameters.
     If there are no remaining arguments, the positional parameters
     are unset.

参见

  1. 我在Ask Ubuntu上的简短回答:如何在脚本中更改参数的值?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接