【问题标题】:How to get the second last argument from shell script?如何从 shell 脚本中获取倒数第二个参数?
【发布时间】:2012-06-18 18:36:37
【问题描述】:

我想将倒数第二项分配给 shell 程序。目前我是这样做的:

file1_tmp="${@: -2}"
oldIFS=$IFS
IFS=" "
count=0
for value in $file1; do
  if [[ count -e 0 ]]; then
    file1=$value
  fi
    count=1
done
oldIFS=$IFS 

我确信有一种更简单的方法可以做到这一点。那么如何以尽可能少的行从 shell 脚本输入中获取倒数第二个参数呢?

【问题讨论】:

    标签: bash unix arguments sh


    【解决方案1】:
    set -- "first argument" "second argument" \
           "third argument" "fourth argument" \
           "fifth argument"
    second_to_last="${@:(-2):1}"
    echo "$second_to_last"
    

    注意引号,它可以确保带有空格的参数粘在一起——你的原始解决方案没有这样做。

    【讨论】:

    • $@$* 之间的差异在您只检索一个项目时并不重要,因为它们控制后续项目如何连接在一起(或者,视情况而定,不)。我仍然建议$@ 让读者更清楚地知道所需的输出是一个单独的元素,没有发生连接操作。还是您有更具体的问题?
    • ...对于(-2)- 之前的空格,关键是要明确我们想要@987654327 的解析器@ 被解析为单个标记。这两种方法都可以实现。
    • 我发现 (-2) 这令人困惑,因为它也用于数组和子 shell。我想这不是这里使用的方式。
    • 确定数组索引是一个具有数学结果的操作,因此 bash 的解析器在算术上下文中运行(与$(( )) 创建的上下文相同);所以括号与它们在任何其他数学运算中的含义相同,因为没有隐含子外壳的分组/优先级/操作顺序。
    【解决方案2】:

    在 bash/ksh/zsh 你可以简单地${@: -2:1}

    $ set a b c d 
    $ echo ${@: -1:1}
    c
    

    在 POSIX sh 中你可以使用eval:

    $ set a b c d 
    $ echo $(eval "echo \$$(($#-2))")
    c
    

    【讨论】:

    • 此答案中的引用对于 zsh 是正确的,但在任何符合 POSIX 的 shell(例如 bash 或 ksh)中都不正确。
    • 这可以在没有 eval 的 Bourne 中完成——例如,通过在函数内移动 args:penultimate() { while [ "$#" -gt 2 ]; do shift; done; printf '%s\n' "$1"; }; penultimate "$@"
    • (这是我以前因为对命名草率而踢我的地方——这不是有效的 [1970 年代] Bourne,它不支持 $(( ));相反,它是有效的 [1990 年代] POSIX sh )。
    • 当我运行你的第一个 sn-p 时,$ echo ${@: -1:1} 打印出 d。你不是说$ echo ${@: -2:1} 吗?
    【解决方案3】:
    n=$(($#-1))
    second_to_last=${!n}
    echo "$second_to_last"
    

    【讨论】:

      【解决方案4】:

      所有 bash 版本都有一些选项:

      $ set -- aa bb cc dd ee ff
      $ echo "${@: -2:1}   ${@:(-2):1}   ${@:(~1):1}   ${@:~1:1}   ${@:$#-1:1}"
      ee   ee   ee   ee   ee
      

      (~) 是按位否定运算符(在算术评估部分搜索)。
      这意味着翻转所有位

      选择甚至可以用(整数)变量来完成:

      $ a=1  ; b=-a; echo "${@:b-1:1}   ${@:(b-1):1}   ${@:(~a):1}   ${@:~a:1}   ${@:$#-a:1}"
      ee   ee   ee   ee   ee
      
      $ a=2  ; b=-a; echo "${@:b-1:1}   ${@:(b-1):1}   ${@:(~a):1}   ${@:~a:1}   ${@:$#-a:1}"
      dd   dd   dd   dd   dd
      

      对于非常旧的 shell,你必须使用 eval:

      eval "printf \"%s\n\" \"\$$(($#-1))\""
      

      【讨论】:

        猜你喜欢
        • 2020-10-23
        • 1970-01-01
        • 2015-03-19
        • 2021-07-31
        • 2022-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多