$1
是第一个论点。
$@
是所有人。
如何找到传递给Shell脚本的最后一个参数?
${!#}
不同于${@: -1}
,它也适用于参数扩展。您可以使用进行测试bash -c 'echo ${!#%.*}' arg1.out arg2.out arg3.out
。
$1
是第一个论点。
$@
是所有人。
如何找到传递给Shell脚本的最后一个参数?
${!#}
不同于${@: -1}
,它也适用于参数扩展。您可以使用进行测试bash -c 'echo ${!#%.*}' arg1.out arg2.out arg3.out
。
Answers:
这有点hack:
for last; do true; done
echo $last
这个也是非常可移植的(再次,应该与bash,ksh和sh一起使用)并且它不会改变参数,这可能很好。
它使用这样的事实:for
如果您不告诉它要进行循环的内容,则隐式地循环遍历参数;并且,事实是for循环变量没有范围:它们保留设置为的最后一个值。
true
是POSIX的一部分。
for last in "$@"; do :; done
还使意图更加清晰。
这仅适用于Bash:
echo "${@: -1}"
${@:$#}
是仅适用于$@
。如果要使用复制$@
到新数组arr=("$@")
,${arr[@]:$#}
则未定义。这是因为扩展中$@
未包含第0个元素"$@"
。
$#
是遍历数组,因为在Bash中,数组是稀疏的,虽然$#
会显示数组中的元素数量,但不一定指向最后一个元素(或element + 1)。换句话说,不应该对索引for ((i = 0; i++; i < $#)); do something "${array[$i]}"; done
执行for element in "${array[@]}"; do something "$element"; done
或迭代:for index in "${!array[@]}"; do something "$index" "${array[$index]}"; done
如果您需要对索引值进行操作。
$ set quick brown fox jumps
$ echo ${*: -1:1} # last argument
jumps
$ echo ${*: -1} # or simply
jumps
$ echo ${*: -2:1} # next to last
fox
该空间是必需的,这样它就不会被解释为默认值。
请注意,这仅适用于bash。
${@: 1:$#-1}
echo ${@: -1} ${@: 1:$#-1}
,最后一个变为第一个,其余的向下滑动
对于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
$BASH_ARGV
不能在bash函数内部工作(除非我做错了)。
BASH_ARGV
将产生的是给定的最后一个arg的值,而不是简单的“最后一个值”。例如!:如果仅提供一个参数,则调用shift ${@:$#}
不会产生任何结果(因为您移出了唯一的一个参数!),但是,BASH_ARGV
仍然会(以前)为您提供最后一个参数。
使用索引并结合以下长度:
echo ${@:${#@}}
请注意,这仅适用于bash。
echo ${@:$#}
试图将最后一个参数与所有先前的参数分开时发现了这一点。虽然某些答案确实有最后一个论点,但如果您还需要其他所有参数,它们对您的帮助不大。这样效果更好:
heads=${@:1:$#-1}
tail=${@:$#}
请注意,这仅适用于bash。
${@: -1}
了最后,并${@: -2:1}
为倒数第二(等等...)。示例:bash -c 'echo ${@: -1}' prog 0 1 2 3 4 5 6
prints 6
。为了保持这种电流AgileZebra的方法,使用${@:$#-1:1}
获得倒数第二。示例:bash -c 'echo ${@:$#-1:1}' prog 0 1 2 3 4 5 6
prints 5
。(并${@:$#-2:1}
获得第三名,依此类推...)
$((...))
减去1,您可以简单地使用${@:1:$# - 1}
。
这适用于所有POSIX兼容的shell:
eval last=\${$#}
资料来源:http : //www.faqs.org/faqs/unix-faq/faq/part2/section-12.html
$#
任意字符串的方法(我认为不是)。eval last=\"\${$#}\"
也可以,显然是正确的。不明白为什么不需要引号。
这是我的解决方案:
eval
码:
ntharg() {
shift $1
printf '%s\n' "$1"
}
LAST_ARG=`ntharg $# "$@"`
"$1"
和之间添加引号"$#"
(请参见unix.stackexchange.com/a/171347的出色答案)。其次,echo
可悲的是不可移植(尤其是-n
),因此printf '%s\n' "$1"
应该使用它。
echo -n
,但是我不知道任何echo "$1"
会失败的posix系统。无论如何,printf
确实更可预测-已更新。
ntharg 1 -n
或ntharg 1 --
在各种系统上可能产生不同的结果。您现在拥有的代码是安全的!
从最旧到最新的解决方案:
最便携的解决方案,甚至更旧sh
(可使用空格和glob字符)(无循环,速度更快):
eval printf "'%s\n'" "\"\${$#}\""
从bash 2.01版本开始
$ set -- The quick brown fox jumps over the lazy dog
$ printf '%s\n' "${!#} ${@:(-1)} ${@: -1} ${@:~0} ${!#}"
dog dog dog dog dog
对于ksh,zsh和bash:
$ printf '%s\n' "${@: -1} ${@:~0}" # the space beetwen `:`
# and `-1` is a must.
dog dog
对于“倒数第二个”:
$ printf '%s\n' "${@:~1:1}"
lazy
使用printf解决任何以破折号开头的参数问题(例如 -n
)。
对于所有外壳程序和较旧版本sh
(适用于空格和glob字符):
$ set -- The quick brown fox jumps over the lazy dog "the * last argument"
$ eval printf "'%s\n'" "\"\${$#}\""
The last * argument
或者,如果您想设置一个last
变量:
$ eval last=\${$#}; printf '%s\n' "$last"
The last * argument
对于“倒数第二个”:
$ eval printf "'%s\n'" "\"\${$(($#-1))}\""
dog
如果您正在使用Bash> = 3.0
echo ${BASH_ARGV[0]}
echo ${BASH_ARGV[1]}
ARGV
代表“参数向量”。
shift `expr $# - 1`
echo "$1"
这会将参数移动参数的数量减1,并返回剩余的第一个(也是唯一的)参数,它将是最后一个。
我仅在bash中进行了测试,但它也应该在sh和ksh中工作。
shift $(($# - 1))
-无需外部实用程序。适用于Bash,ksh,zsh和破折号。
$((...))
语法。
printf '%s\n' "$1"
以避免来自的意外行为echo
(例如-n
)。
如果要以一种非破坏性的方式进行操作,则一种方法是将所有参数传递给一个函数并返回最后一个参数:
#!/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
子句轻松地调整该行为。
我发现@AgileZebra的答案(加上@starfry的评论)最有用,但是它设置heads
为标量。数组可能更有用:
heads=( "${@:1:$(($# - 1))}" )
tail=${@:${#@}}
请注意,这仅适用于bash。
echo "${heads[-1]}"
打印中的最后一个元素heads
。还是我错过了什么?
使用eval
以下解决方案:
last=$(eval "echo \$$#")
echo $last
!
因此,last="${!#}"
将使用相同的方法(更直接,更间接,更
=
。
${!#}
,但一般而言并非如此:如果内容包含文字空白,例如,仍需要用引号引起来last='two words'
。$()
无论内容如何,仅空白是安全的。
阅读以上答案后,我编写了一个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
以下将设置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
echo $argv[$#argv]
现在,我只需要添加一些文本,因为我的答案太短而无法发布。我需要添加更多文本进行编辑。
$argv
但没有$#argv
- $argv[(count $argv)]
在鱼中起作用)。
这是我的复制功能的一部分:
eval echo $(echo '$'"$#")
要在脚本中使用,请执行以下操作:
a=$(eval echo $(echo '$'"$#"))
说明(最嵌套在前):
$(echo '$'"$#")
返回$[nr]
where [nr]
是参数的数量。例如,字符串$123
(未扩展)。echo $123
求值时,返回123rd参数的值。eval
只是扩展$123
为参数的值,例如last_arg
。这被解释为字符串并返回。从2015年年中开始与Bash合作。
尝试以下脚本查找最后一个参数
# 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
谢谢。
有一种更简洁的方法可以执行此操作。可以将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