代码之家  ›  专栏  ›  技术社区  ›  Thomas

获取传递给shell脚本的最后一个参数

  •  235
  • Thomas  · 技术社区  · 16 年前

    $1 是第一个论点。
    $@ 都是这样。

    我怎样才能找到最后一个传递给shell的参数 脚本?

    26 回复  |  直到 7 年前
        1
  •  157
  •   Laurence Gonsalves    16 年前

    这有点像黑客:

    for last; do true; done
    echo $last
    

    这一个也是非常可移植的(同样,应该可以与bash、ksh和sh一起使用),并且它不会改变参数,这可能很好。

    它使用的事实是 for 如果不告诉参数循环什么,并且for循环变量没有作用域,则隐式循环这些参数:它们保留设置为的最后一个值。

        2
  •  262
  •   Dennis Williamson    16 年前

    这只是bash:

    echo "${@: -1}"
    
        3
  •  74
  •   Zombo tliff    12 年前
    $ set quick brown fox jumps
    
    $ echo ${*: -1:1} # last argument
    jumps
    
    $ echo ${*: -1} # or simply
    jumps
    
    $ echo ${*: -2:1} # next to last
    fox
    

    空间是必要的,这样它就不会被解释为 default value .

        4
  •  71
  •   Kevin Little    15 年前

    对于bash 3.0或更高版本,最简单的答案是

    _last=${!#}       # *indirect reference* to the $# variable
    # or
    _last=$BASH_ARGV  # official built-in (but takes more typing :)
    

    就是这样。

    $ cat lastarg
    #!/bin/bash
    # echo the last arg given:
    _last=${!#}
    echo $_last
    _last=$BASH_ARGV
    echo $_last
    for x; do
       echo $x
    done
    

    输出为:

    $ lastarg 1 2 3 4 "5 6 7"
    5 6 7
    5 6 7
    1
    2
    3
    4
    5 6 7
    
        5
  •  27
  •   Mark Byers    16 年前

    使用与以下长度组合的索引:

    echo ${@:${#@}} 
    
        6
  •  24
  •   Tahsin Turkoz    9 年前

    以下内容适用于您。@用于参数数组。意味着$是参数数组的长度。所以结果是最后一个元素:

    ${@:$#} 
    

    例子:

    function afunction{
        echo ${@:$#} 
    }
    afunction -d -o local 50
    #Outputs 50
    
        7
  •  21
  •   AgileZebra    10 年前

    当试图将最后一个参数与前一个参数分开时发现了这个问题。 虽然有些答案确实得到了最后一个论点,但如果您需要所有其他参数,它们也没有多大帮助。这样做效果更好:

    heads=${@:1:$(($# - 1))}
    tail=${@:$#}
    
        8
  •  18
  •   poiuz    14 年前

    这适用于所有与posix兼容的shell:

    eval last=\${$#}
    

    来源: http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html

        9
  •  8
  •   dusan    16 年前

    如果使用bash>=3.0

    echo ${BASH_ARGV[0]}
    
        10
  •  8
  •   Michał Å rajer    8 年前

    这是我的解决方案:

    • 相当可移植(所有posix sh、bash、ksh、zsh)都可以工作
    • 不移动原始参数(移动副本)。
    • 不使用 邪恶的 eval
    • 不遍历整个列表
    • 不使用外部工具

    代码:

    ntharg() {
        shift $1
        printf '%s\n' "$1"
    }
    LAST_ARG=`ntharg $# "$@"`
    
        11
  •  3
  •   Isaac    7 年前

    对于ksh、zsh和bash:

    $ set -- The quick brown fox jumps over the lazy dog
    
    $ echo "${@:~0}"
    dog
    

    至于“倒数第二名”:

    $ echo "${@:~1:1}"
    lazy
    

    解决任何以破折号开头的论点的问题(例如 -n )用途:

    $ printf '%s\n' "${@:~0}"
    dog
    

    以及正确处理空间和全局字符的方法 sh 是:

    $ set -- The quick brown fox jumps over the lazy dog "the * last argument"
    
    $ eval echo "\"\${$#}\""
    The last * argument
    

    或者,如果要设置 last var:

    $ eval last=\${$#}; echo "$last"
    The last * argument
    

    至于“倒数第二名”:

    $ eval echo "\"\${$(($#-1))}\""
    dog
    
        12
  •  2
  •   Laurence Gonsalves    16 年前
    shift `expr $# - 1`
    echo "$1"
    

    这将按参数数目减1来移动参数,并返回第一个(也是唯一一个)剩余参数,这将是最后一个。

    我只在bash中测试过,但它也应该在sh和ksh中工作。

        13
  •  2
  •   paxdiablo    16 年前

    如果您想以非破坏性的方式进行,一种方法是将所有参数传递给一个函数并返回最后一个参数:

    #!/bin/bash
    
    last() {
            if [[ $# -ne 0 ]] ; then
                shift $(expr $# - 1)
                echo "$1"
            #else
                #do something when no arguments
            fi
    }
    
    lastvar=$(last "$@")
    echo $lastvar
    echo "$@"
    
    pax> ./qq.sh 1 2 3 a b
    b
    1 2 3 a b
    

    如果你不是真的 照顾 关于保留其他参数,您在函数中不需要它,但是我很难想到这样一种情况,即除非已经处理了其他参数,否则您将永远不希望保留这些参数,在这种情况下,我将使用process/shift/process/shift/。顺序处理它们的方法。

    我假设你想留下他们是因为你 没有 采用顺序法。此方法还处理没有参数的情况,返回“”。您可以通过插入注释掉的 else 条款。

        14
  •  2
  •   Palec    10 年前

    对于TCSH:

    set X = `echo $* | awk -F " " '{print $NF}'`
    somecommand "$X"
    

    我很肯定这将是一个可移植的解决方案,除了任务。

        15
  •  1
  •   Mikael S    16 年前

    使用的解决方案 eval :

    last=$(eval "echo \$$#")
    
    echo $last
    
        16
  •  1
  •   David E.    13 年前

    在阅读了上面的答案之后,我编写了一个q&d shell脚本(应该在sh和bash上工作),在pgm.cpp上运行g++来生成可执行映像pgm。它假定命令行上的最后一个参数是文件名(.cpp是可选的),而所有其他参数都是选项。

    #!/bin/sh
    if [ $# -lt 1 ]
    then
        echo "Usage: `basename $0` [opt] pgm runs g++ to compile pgm[.cpp] into pgm"
        exit 2
    fi
    OPT=
    PGM=
    # PGM is the last argument, all others are considered options
    for F; do OPT="$OPT $PGM"; PGM=$F; done
    DIR=`dirname $PGM`
    PGM=`basename $PGM .cpp`
    # put -o first so it can be overridden by -o specified in OPT
    set -x
    g++ -o $DIR/$PGM $OPT $DIR/$PGM.cpp
    
        17
  •  1
  •   Paweł Nadolski    12 年前

    将设置以下内容 LAST 不改变当前环境的最后一个参数:

    LAST=$({
       shift $(($#-1))
       echo $1
    })
    echo $LAST
    

    如果不再需要其他参数,可以将其简化为:

    shift $(($#-1))
    echo $1
    

    出于可移植性原因,以下内容:

    shift $(($#-1));
    

    可替换为:

    shift `expr $# - 1`
    

    替代也 $() 通过后引号,我们得到:

    LAST=`{
       shift \`expr $# - 1\`
       echo $1
    }`
    echo $LAST
    
        18
  •  1
  •   Alireza    11 年前
    echo $argv[$#argv]
    

    现在我只需要添加一些文本,因为我的答案太短,无法发布。我需要添加更多的文本来编辑。

        19
  •  1
  •   EndlosSchleife    11 年前

    我发现@agilezebra的回答(加上@starfray的评论)最有用,但它设置了 heads 到标量。数组可能更有用:

    heads=( "${@:1:$(($# - 1))}" )
    tail=${@:${#@}}
    
        20
  •  1
  •   Palec    10 年前

    这是我的复制功能的一部分:

    eval echo $(echo '$'"$#")
    

    要在脚本中使用,请执行以下操作:

    a=$(eval echo $(echo '$'"$#"))
    

    解释(最嵌套的第一个):

    1. $(echo '$'"$#") 收益率 $[nr] 在哪里? [nr] 是参数数目。例如字符串 $123 (未膨胀的)
    2. echo $123 计算时返回123rd参数的值。
    3. eval 只是扩张 123美元 参数的值,例如 last_arg . 这被解释为字符串并返回。

    自2015年年中起与Bash合作。

        21
  •  1
  •   Tom Hale    7 年前

    为了 bash , this comment 建议非常优雅:

    echo "${@:$#}"
    
        22
  •  0
  •   Craig Trader    16 年前
    #! /bin/sh
    
    next=$1
    while [ -n "${next}" ] ; do
      last=$next
      shift
      next=$1
    done
    
    echo $last
    
        23
  •  0
  •   Ranjithkumar T    12 年前

    尝试下面的脚本查找最后一个参数

     # cat arguments.sh
     #!/bin/bash
     if [ $# -eq 0 ]
     then
     echo "No Arguments supplied"
     else
     echo $* > .ags
     sed -e 's/ /\n/g' .ags | tac | head -n1 > .ga
     echo "Last Argument is: `cat .ga`"
     fi
    

    输出:

     # ./arguments.sh
     No Arguments supplied
    
     # ./arguments.sh testing for the last argument value
     Last Argument is: value
    

    谢谢。

        24
  •  0
  •   tekbot    11 年前

    有一种更简洁的方法可以做到这一点。bash脚本的参数可以放入一个数组中,这使得处理元素更加简单。下面的脚本将始终打印传递给脚本的最后一个参数。

      argArray=( "$@" )                        # Add all script arguments to argArray
      arrayLength=${#argArray[@]}              # Get the length of the array
      lastArg=$((arrayLength - 1))             # Arrays are zero based, so last arg is -1
      echo ${argArray[$lastArg]}
    

    样本输出

    $ ./lastarg.sh 1 2 buckle my shoe
    shoe
    
        25
  •  0
  •   Jurij    7 年前

    使用参数扩展(删除匹配的开始):

    args="$@"
    last=${args##* }
    

    也很容易在最后一次之前得到所有:

    prelast=${args% *}
    
        26
  •  -1
  •   zw963    11 年前

    这种格式可以在Slackware和Cygwin中使用。

    “$x[@]:(-1)”,如果与$@一起使用,“$@:(-1)”

    意思是:$@:(n),将返回n个索引后的所有元素(包括n)。 1是最后一名。