在“$ @”中的最后一个参数之前提取参数
我正在尝试创build一个Bash脚本,将从命令行中提取的最后一个参数提取到其他地方使用的variables中。 这是我正在处理的脚本:
#!/bin/bash # compact - archive and compact file/folder(s) eval LAST=\$$# FILES="$@" NAME=$LAST # Usage - display usage if no parameters are given if [[ -z $NAME ]]; then echo "compact <file> <folder>... <compressed-name>.tar.gz" exit fi # Check if an archive name has been given if [[ -f $NAME ]]; then echo "File exists or you forgot to enter a filename. Exiting." exit fi tar -czvpf "$NAME".tar.gz $FILES
由于第一个参数可以是任何数字,我必须find一种方法来提取最后一个参数(例如,compact file.a file.b file.d files-abd.tar.gz)。 由于现在档案名称将被包含在文件中以进行压缩。 有没有办法做到这一点?
要从数组中删除最后一项,你可以使用这样的东西:
#!/bin/bash length=$(($#-1)) array=${@:1:$length} echo $array
last_arg="${!#}"
已经发布了几个解决scheme; 但是我会build议重构您的脚本,以便存档名称是第一个参数,而不是最后一个。 那么这很简单,因为你可以使用内build的shift
来删除第一个参数:
ARCHIVENAME="$1" shift # Now "$@" contains all of the arguments except for the first
这是我的脚本
last=${@:$#} # last parameter other=${*%${!#}} # all parameters except the last
我喜欢因为是一个非常紧凑的解决scheme
谢谢你们,把它完成,inheritance人最后的bash脚本:
#!/bin/bash # compact - archive and compress file/folder(s) # Extract archive filename for variable ARCHIVENAME="${!#}" # Remove archive filename for file/folder list to backup length=$(($#-1)) FILES=${@:1:$length} # Usage - display usage if no parameters are given if [[ -z $@ ]]; then echo "compact <file> <folder>... <compressed-name>.tar.gz" exit fi # Tar the files, name archive after last file/folder if no name given if [[ ! -f $ARCHIVENAME ]]; then tar -czvpf "$ARCHIVENAME".tar.gz $FILES; else tar -czvpf "$ARCHIVENAME".tar.gz "$@" fi
只需要删除Krzysztof Klimonda解决scheme中使用的length
variables:
( set -- 1 2 3 4 5 echo "${@:1:($#-1)}" # 1 2 3 4 echo "${@:(-$#):($#-1)}" # 1 2 3 4 )
#!/bin/bash lastidx=$# lastidx=`expr $lastidx - 1` eval last='$'{$lastidx} echo $last
尝试:
if [ "$#" -gt '0' ]; then /bin/echo "${!#}" "${@:1:$(($# - 1))} fi
我会join这个评论,但没有足够的声誉,答案有点长。 希望它不介意。
正如@func所述:
说明:last_arg = “$ {#!}”
怎么运行的:
$ {!PARAM}表示间接级别。 您没有引用PARAM本身,而是存储在PARAM中的值(将PARAM视为指向值的指针)。
$ {#}扩展为参数的数量(注意: $ 0 – 脚本名称 – 在这里不计算在内)。
考虑下面的执行:
$./myscript.sh p1 p2 p3
并在myscript.sh中
#!/bin/bash echo "Number of params: ${#}" # 3 echo "Last parameter using '\${!#}': ${!#}" # p3 echo "Last parameter by evaluating positional value: $(eval LASTP='$'${#} ; echo $LASTP)" # p3
因此,您可以将$ {!#}想象为上述eval用法的快捷方式,这正好是上述方法 – 评估存储在给定参数中的值,此处参数为3,并保存位置参数$ 3
现在如果你想要除了最后一个之外的所有参数,你可以使用子串删除$ {PARAM%PATTERN} ,其中%符号的意思是“从string的末尾删除最短匹配模式” 。
因此在我们的脚本中:
echo "Every parameter except the last one: ${*%${!#}}"
你可以在这里读到一些东西: 参数扩展
#!/ bin / sh的 eval last ='$'$# 同时testing$#-gt 1; 做 list =“$ list $ 1” 转移 DONE echo $ list $ last
我找不到在$@
上使用数组下标符号的方法,所以这是我可以做的最好的:
#!/bin/bash args=("$@") echo "${args[$(($#-1))]}"
你确定这个奇特的脚本比tar的简单别名更好吗?
alias compact="tar -czvpf"
用法是:
compact ARCHIVENAME FILES...
其中FILES可以是file1 file2
或像*.html
这样的*.html
这个脚本可能适用于你 – 它返回参数的子范围,并可以从另一个脚本调用。
它运行的例子:
$ args_get_range 2 -2 yab "c 1" defg 'b' 'c 1' 'd' 'e' $ args_get_range 1 2 n arg1 arg2 arg1 arg2 $ args_get_range 2 -2 y arg1 arg2 arg3 "arg 4" arg5 'arg2' 'arg3' $ args_get_range 2 -1 y arg1 arg2 arg3 "arg 4" arg5 'arg2' 'arg3' 'arg 4' # You could use this in another script of course # by calling it like so, which puts all # args except the last one into a new variable # called NEW_ARGS NEW_ARGS=$(args_get_range 1 -1 y "$@")
args_get_range.sh
#!/usr/bin/env bash function show_help() { IT=" Extracts a range of arguments from passed in args and returns them quoted or not quoted. usage: START END QUOTED ARG1 {ARG2} ... eg # extract args 2-3 $ args_get_range.sh 2 3 n arg1 arg2 arg3 arg2 arg3 # extract all args from 2 to one before the last argument $ args_get_range.sh 2 -1 n arg1 arg2 arg3 arg4 arg5 arg2 arg3 arg4 # extract all args from 2 to 3, quoting them in the response $ args_get_range.sh 2 3 y arg1 arg2 arg3 arg4 arg5 'arg2' 'arg3' # You could use this in another script of course # by calling it like so, which puts all # args except the last one into a new variable # called NEW_ARGS NEW_ARGS=\$(args_get_range.sh 1 -1 \"\$@\") " echo "$IT" exit } if [ "$1" == "help" ] then show_help fi if [ $# -lt 3 ] then show_help fi START=$1 END=$2 QUOTED=$3 shift; shift; shift; if [ $# -eq 0 ] then echo "Please supply a folder name" exit; fi # If end is a negative, it means relative # to the last argument. if [ $END -lt 0 ] then END=$(($#+$END)) fi ARGS="" COUNT=$(($START-1)) for i in "${@:$START}" do COUNT=$((COUNT+1)) if [ "$QUOTED" == "y" ] then ARGS="$ARGS '$i'" else ARGS="$ARGS $i" fi if [ $COUNT -eq $END ] then echo $ARGS exit; fi done echo $ARGS