【问题标题】:Remove first element from $@ in bash [duplicate]从 bash 中的 $@ 中删除第一个元素 [重复]
【发布时间】:2023-03-12 12:26:01
【问题描述】:

我正在编写一个 bash 脚本,它需要遍历传递给脚本的参数。但是,第一个参数不应该被循环,而是需要在循环之前进行检查。

如果我不必删除第一个元素,我可以这样做:

for item in "$@" ; do
  #process item
done

我可以修改循环以检查它是否在第一次迭代中并更改行为,但这似乎太老套了。必须有一种简单的方法来提取第一个参数,然后遍历其余参数,但我找不到它。

【问题讨论】:

    标签: arrays bash


    【解决方案1】:

    使用shift?

    http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_07.html

    基本上,为循环前的第一个参数读取$1(或$0,如果您要检查的是脚本名称),然后使用shift,然后循环剩余的$@

    【讨论】:

    • 看,我知道有一个简单的答案。 :)
    • 值得一票,但 丹尼斯的回答被接受 :)
    • @mgarciaisaia 似乎更适合 OP 的要求:删除第一项
    • 这完全是模糊的——不如下面的@nos 回答有用
    • 有一个例子会很有用,以避免不得不去一个可能有一天会消失的外部链接。
    【解决方案2】:

    另一种变体使用数组切片:

    for item in "${@:2}"
    do
        process "$item"
    done
    

    如果由于某种原因您想保留参数,这可能很有用,因为 shift 具有破坏性。

    【讨论】:

    • 感谢 ${@:2}。好东西!
    • 正是我想要的。现在不需要 temp 变量来取消引用 "${!1}${@:2}" 中的第一个参数
    • @Herms 这应该是公认的答案,更具可读性且无破坏性(相对于 shift)
    • 漂亮,非常感谢。
    • 从技术上讲,当前接受的答案是正确的,但这在技术上和实践上都是正确的(因为 shift 具有破坏性)。这是一个更好的答案。所以理想情况下应该是答案。
    【解决方案3】:
    firstitem=$1
    shift;
    for item in "$@" ; do
      #process item
    done
    

    【讨论】:

    • 记住$0一般是脚本名。
    • +1 用于展示一个简单的例子;请注意,in "$@" 部分是隐含的,可以省略。
    • @mklement0 你是说你可以做“for item; do”?
    • @DavidDoria:是的,你可以。试试set -- 1 'two' 'three four'; for item; do echo "[$item]"; done
    【解决方案4】:
    q=${@:0:1};[ ${2} ] && set ${@:2} || set ""; echo $q
    

    编辑

    > q=${@:1}
    # gives the first element of the special parameter array ${@}; but ${@} is unusual in that it contains (? file name or something ) and you must use an offset of 1;
    
    > [ ${2} ] 
    # checks that ${2} exists ; again ${@} offset by 1
        > && 
        # are elements left in        ${@}
          > set ${@:2}
          # sets parameter value to   ${@} offset by 1
        > ||
        #or are not elements left in  ${@}
          > set ""; 
          # sets parameter value to nothing
    
    > echo $q
    # contains the popped element
    

    一个带有规则数组的pop示例

       LIST=( one two three )
        ELEMENT=( ${LIST[@]:0:1} );LIST=( "${LIST[@]:1}" ) 
        echo $ELEMENT
    

    【讨论】:

    • 请同时解释代码以更具教育意义。
    • q=${@:0:1} (顺便说一句,您的解释错误地将其引用为q=${@:1})应该是q=${@:1:1} 更清楚:$@ 以索引 1 开头,大概是并行的显式 $1, $2, ... 参数 - 元素 0 具有 no 值(与其显式对应物 $0 不同,它反映了 shell / 脚本文件)。 [ ${2} ]break 应该 $2 包含嵌入的空格;如果您改用[[ ${2} ]],就不会遇到这个问题。也就是说,不需要条件和 || 分支:如果只有 1 个参数,${@:2} 将简单地扩展为空字符串(续)。
    • (cont'd) 但是,您应该使用 set -- 以确保恰好看起来像选项的参数不会被 set 解释为这样,并且您应该双引号${@:2} 引用和$q 引用在echo 语句中。此时我们得到:q=${@:1:1}; set -- "${@:2}"; echo "$q"。然而,q=${@:1:1} 只是另一种(更繁琐的)表达$1 的方式,其余的基本上重新实现了shift 命令;使用这些功能我们很容易得到:q=$1; shift; echo "$q".
    • @mklement0 我想知道在哪里放置 printf 来清理路径的好地方? (我希望我能更清楚)
    • 很遗憾,我不明白。有哪些路径?用什么方式清洁?
    猜你喜欢
    • 2020-07-01
    • 2013-05-27
    • 2019-12-29
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    相关资源
    最近更新 更多