Wyodrębnij parametry przed ostatnim parametrem w "$@"
Próbuję stworzyć skrypt Bash, który wyodrębni ostatni parametr podany z wiersza poleceń do zmiennej, która będzie używana gdzie indziej. Oto scenariusz, nad którym pracuję:
#!/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
Ponieważ pierwsze parametry mogą być dowolnej liczby, muszę znaleźć sposób na wyodrębnienie ostatniego parametru (np. plik Kompaktowy.plik.plik B.d files-A-b-D. tar.gz). Jak to jest teraz nazwa archiwum będzie zawarte w plikach do kompaktu. Jest na to sposób?
14 answers
Aby usunąć ostatni element z tablicy możesz użyć czegoś takiego:
#!/bin/bash
length=$(($#-1))
array=${@:1:$length}
echo $array
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 01:33:38
last_arg="${!#}"
Kilka rozwiązań zostało już opublikowanych, jednak radzę zrestrukturyzować skrypt tak, aby nazwa archiwum była parametrem first, a nie ostatnim. To jest naprawdę proste, ponieważ można użyć shift
Wbudowany aby usunąć pierwszy parametr:
ARCHIVENAME="$1"
shift
# Now "$@" contains all of the arguments except for the first
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 21:55:14
Przenośne i kompaktowe rozwiązania
Tak robię w moich skryptach
last=${@:$#} # last parameter
other=${*%${!#}} # all parameters except the last
Podoba mi się, ponieważ jest to bardzo kompaktowe rozwiązanie.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 14:52:36
Thanks guys, got it done, heres the final bash script:
#!/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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 21:36:31
Wystarczy zrzucić zmienną length
zastosowaną w rozwiązaniu Krzysztofa Klimondy:
(
set -- 1 2 3 4 5
echo "${@:1:($#-1)}" # 1 2 3 4
echo "${@:(-$#):($#-1)}" # 1 2 3 4
)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-06 17:47:27
Dodałbym to jako komentarz, ale nie mam wystarczającej reputacji, a odpowiedź i tak trochę się wydłużyła. Mam nadzieję, że to nie przeszkadza.
Jak stwierdził @ func:
Last_arg="${!#}"
Jak to działa:
${!PARAM} wskazuje poziom indrection. Nie odwołujesz się do samej PARAM, ale do wartości przechowywanej w PARAM ( pomyśl o PARAM jako wskaźniku do wartości ).
${#} rozszerza się do liczby parametry (Uwaga: $0 - Nazwa skryptu - nie jest tu liczona).
Rozważ następujące wykonanie:
$./myscript.sh p1 p2 p3
I w 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
Stąd możesz myśleć o ${!#} jako skrót do powyższego zastosowania eval, które wykonuje dokładnie opisane powyżej podejście-oblicza wartość zapisaną w podanym parametrze, tutaj parametr jest 3 i utrzymuje argument pozycyjny$3
Teraz, jeśli chcesz wszystkie params oprócz ostatni, możesz użyć usuwania podłańcucha ${PARAM%PATTERN} gdzie % znak oznacza 'Usuń najkrótszy pasujący wzór z końca łańcucha' .
Stąd w naszym skrypcie:
echo "Every parameter except the last one: ${*%${!#}}"
Możesz tu coś przeczytać: rozszerzenie parametru
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-25 08:46:13
#!/bin/bash
lastidx=$#
lastidx=`expr $lastidx - 1`
eval last='$'{$lastidx}
echo $last
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 01:23:56
Jesteś pewien, że ten wymyślny skrypt jest lepszy niż zwykły alias do tar?
alias compact="tar -czvpf"
Użycie to:
compact ARCHIVENAME FILES...
Gdzie pliki mogą być file1 file2
lub takie jak *.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-06 11:42:46
Try:
if [ "$#" -gt '0' ]; then
/bin/echo "${!#}" "${@:1:$(($# - 1))}
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-16 18:10:10
#!/bin/sh eval last='$'$# while test $# -gt 1; do list="$list $1" shift done echo $list $last
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 01:20:19
Nie mogę znaleźć sposobu na użycie notacji array-subscript na $@
, więc to jest najlepsze, co mogę zrobić:
#!/bin/bash
args=("$@")
echo "${args[$(($#-1))]}"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-01 01:41:26
Ten skrypt może działać dla Ciebie-zwraca podzbiór argumentów i może być wywołany z innego skryptu.
Przykłady jego działania:
$ args_get_range 2 -2 y a b "c 1" d e f g
'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} ...
e.g.
# 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-13 20:04:57
Tablica bez ostatniego parametru:
array=${@:1:$#-1}
Ale to jest bashism : (. Odpowiednie rozwiązania polegałyby na przesunięciu i dodaniu do zmiennej w miarę korzystania przez innych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-24 05:04:56