【问题标题】:How is the correct way to exapand braces in a "for loop" BASH to positional parameters?将“for循环”BASH中的大括号扩展为位置参数的正确方法是什么?
【发布时间】:2019-05-07 00:02:03
【问题描述】:

当我尝试在 BASH 中编写这个函数时

function Odds () for i in {1..${#@}..2} ; do echo $i; done

我期望像

这样的输出

1 3 5...

取决于传递给函数的参数数量。

但有效的输出是扩展了 ${#@} 的字符串。

{1..5..2}

我有一些猜想,但是......任何事情......发生了什么以及如何避免这种情况并获得理想的输出?

【问题讨论】:

标签: bash loops for-loop expansion braces


【解决方案1】:

问题在于大括号扩展是在之前 参数替换完成的。因此,大括号扩展不能与变量一起使用。

选项 1:序列

如果您安装了seq(这在 Linux 上很常见),请尝试:

function Odds () { seq 1 2 "${#@}"; }

seq 1 2 "${#@}" 返回以1 开头并每次递增2 直到达到${#@} 的数字。

例如:

$ Odds a b c d e
1
3
5

注意:function 表示法不是必需的,并且会限制兼容性(它不是 POSIX)。 Odds 可以不用它来定义:

Odds () { seq 1 2 "${#@}"; }

选项 2:bash

或者,只使用 bash,定义:

function Odds () { for ((i=1; i<=${#@}; i=i+2)); do echo "$i"; done; }

这会产生相同的输出:

$ Odds a b c d e
1
3
5

选项 3:POSIX

为了获得最广泛的兼容性,请使用符合 POSIX 标准的函数:

Odds() { i=1; while [ "$i" -le "$#" ]; do echo "$i"; i=$((i+2)); done; }

【讨论】:

  • 我真的很喜欢你的 cmets。特别是这个:“问题是大括号扩展是在参数替换之前完成的。”我试图避免使用 seq ,寻找更“纯”的 bash 代码。无论如何,谢谢!为了学习proporse,我正在尝试学习最便携的编码方式。
  • @DanielBandeira 对于大多数可移植性,应该使用符合POSIX standard 的代码。这就是上面的(新添加的)选项 3。
【解决方案2】:

试试这个:

function Odds () { for i in {1..${@}..2} ; do echo $i; done }

function Odds () { for i in {1..${1}..2} ; do echo $i; done }

【讨论】:

    猜你喜欢
    • 2015-12-10
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    • 2014-11-05
    相关资源
    最近更新 更多