$1
- первый аргумент. [email protected]
- все они.
Как я могу найти последний аргумент, переданный оболочке script?
$1
- первый аргумент. [email protected]
- все они.
Как я могу найти последний аргумент, переданный оболочке script?
Это немного взломать:
for last; do true; done
echo $last
Этот тоже довольно портативный (опять же, должен работать с bash, ksh и sh), и он не сдвигает аргументы, что может быть приятным.
Он использует тот факт, что for
неявно перебирает аргументы, если вы не говорите ему, что делать, и тот факт, что для переменных цикла не охвачен: они сохраняют последнее значение, на которое они были установлены.
Это Bash -одно:
echo "${@: -1}"
$ set quick brown fox jumps
$ echo ${*: -1:1} # last argument
jumps
$ echo ${*: -1} # or simply
jumps
$ echo ${*: -2:1} # next to last
fox
Пространство необходимо, чтобы оно не интерпретировалось как значение по умолчанию.
Самый простой ответ для 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
Используйте индексирование в сочетании с длиной:
echo ${@:${#@}}
Следующие действия будут работать для вас. @- массив аргументов.: означает at. $# - длина массива аргументов. Таким образом, результатом является последний элемент:
${@:$#}
Пример:
function afunction{
echo ${@:$#}
}
afunction -d -o local 50
#Outputs 50
Обнаружено это, если вы хотите отделить последний аргумент от всех предыдущих (ей). Хотя некоторые ответы дают последний аргумент, они не очень помогают, если вам нужны все другие аргументы. Это работает намного лучше:
heads=${@:1:$(($# - 1))}
tail=${@:$#}
Это работает во всех POSIX-совместимых оболочках:
eval last=\${$#}
Источник: http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html
Вот мое решение:
eval
Код:
ntharg() {
shift $1
printf '%s\n' "$1"
}
LAST_ARG='ntharg $# "[email protected]"'
Если вы используете Bash >= 3.0
echo ${BASH_ARGV[0]}
Только для 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:
$ echo "${@: -1} ${@:~0}" # the space beetwen ':' and '-1' is a must.
dog dog
А для "рядом с последним":
$ echo "${@:~1:1}"
lazy
Чтобы обойти любые проблемы с аргументами, начинающимися с тире (например, -n
), используйте printf
:
$ 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
:
$ eval last=\${$#}; echo "$last"
The last * argument
А для "рядом с последним":
$ eval echo "\"\${$(($#-1))}\""
dog
Для bash
этот комментарий предложил очень элегантно:
echo "${@:$#}"
В качестве бонуса, это также работает в zsh
.
shift `expr $# - 1`
echo "$1"
Это сдвигает аргументы на число аргументов минус 1 и возвращает первый (и только) оставшийся аргумент, который будет последним.
Я тестировал только bash, но он должен работать и в sh и ksh.
Если вы хотите сделать это неразрушающим образом, один из способов - передать все аргументы функции и вернуть последний:
#!/bin/bash
last() {
if [[ $# -ne 0 ]] ; then
shift $(expr $# - 1)
echo "$1"
#else
#do something when no arguments
fi
}
lastvar=$(last "[email protected]")
echo $lastvar
echo "[email protected]"
pax> ./qq.sh 1 2 3 a b
b
1 2 3 a b
Если вы действительно не заботитесь о сохранении других аргументов, вам это не нужно в функции, но мне сложно подумать о ситуации, когда вы никогда не захотите сохранить другие аргументы, если они уже были обработаны, и в этом случае я бы использовал метод process/shift/process/shift/... для последовательной обработки их.
Я предполагаю, что вы хотите сохранить их, потому что вы не следовали последовательному методу. Этот метод также обрабатывает случай, когда нет аргументов, возвращающих "". Вы можете легко отрегулировать это поведение, вставив закомментированное предложение else
.
Для tcsh:
set X = `echo $* | awk -F " " '{print $NF}'`
somecommand "$X"
Я уверен, что это будет переносное решение, за исключением назначения.
Решение с использованием eval
:
last=$(eval "echo \$$#")
echo $last
Прочитав ответы выше, я написал оболочку Q & D script (должен работать на sh и bash) для запуска g++ на PGM.cpp для создания исполняемого файла 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]
Теперь мне просто нужно добавить текст, потому что мой ответ был слишком коротким для публикации. Мне нужно добавить текст для редактирования.
Я нашел ответ @AgileZebra (плюс комментарий @starfry) наиболее полезным, но он устанавливает heads
в скаляр. Массив, вероятно, более полезен:
heads=( "${@:1:$(($# - 1))}" )
tail=${@:${#@}}
Это часть моей функции копирования:
eval echo $(echo '$'"$#")
Чтобы использовать в скриптах, сделайте следующее:
a=$(eval echo $(echo '$'"$#"))
Объяснение (наиболее вложенное первое):
$(echo '$'"$#")
возвращает $[nr]
, где [nr]
- количество параметров. Например. строка $123
(нерасширенная).echo $123
возвращает значение 123-го параметра при оценке.eval
просто расширяет $123
до значения параметра, например. last_arg
. Это интерпретируется как строка и возвращается.Работает с Bash по состоянию на середину 2015 года.
#! /bin/sh
next=$1
while [ -n "${next}" ] ; do
last=$next
shift
next=$1
done
echo $last
Попробуйте ниже script найти последний аргумент
# 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 script могут быть перенесены в массив, что упрощает работу с элементами. script ниже всегда будет печатать последний аргумент, переданный script.
argArray=( "[email protected]" ) # 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
Используя расширение параметра (удалить соответствующее начало):
args="[email protected]"
last=${args##* }
Также легко получить все до последнего:
prelast=${args% *}
Этот формат может работать в Slackware и Cygwin.
"$ {x [@]: (- 1)}", если используется с [email protected], "$ {@: (- 1)}"
Это означает: ${@:( N)}, вернет весь элемент после N индекса (включая N), -1 - это вечность.
Это возвращает последний использованный параметр.
$_