J'essaie de créer un script Bash qui extraira le dernier paramètre donné à partir de la ligne de commande dans une variable à utiliser ailleurs. Voici le script sur lequel je travaille:
#!/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
Comme les premiers paramètres peuvent être n’importe quel nombre, je dois trouver un moyen d’extraire le dernier paramètre (par exemple, compact fichier.a fichier.b fichier.d fichiers-a-b-d.tar.gz). Comme il est maintenant, le nom de l'archive sera inclus dans les fichiers à compacter. Y a-t-il un moyen de faire cela?
Pour supprimer le dernier élément du tableau, vous pouvez utiliser quelque chose comme ceci:
#!/bin/bash
length=$(($#-1))
array=${@:1:$length}
echo $array
last_arg="${!#}"
Plusieurs solutions ont déjà été postées. Cependant, je vous conseillerais de restructurer votre script afin que le nom de l'archive soit le paramètre first plutôt que le dernier. Ensuite, c’est très simple, puisque vous pouvez utiliser le shift
intégré pour supprimer le premier paramètre:
ARCHIVENAME="$1"
shift
# Now "$@" contains all of the arguments except for the first
C'est comme ça que je fais dans mes scripts
last=${@:$#} # last parameter
other=${*%${!#}} # all parameters except the last
MODIFIER
Selon certains commentaires (voir ci-dessous), cette solution est plus portable que d'autres.
Veuillez lire le commentaire de Michael Dimmitt pour une explication de son fonctionnement.
Merci les gars, l'avoir fait, voici le dernier script 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
J'ajouterais cela à titre de commentaire, mais je n'ai pas assez de réputation et la réponse a été un peu plus longue de toute façon. J'espère que ça ne te dérange pas.
Comme @func a déclaré:
last_arg = "$ {! #}"
Comment ça marche:
$ {! PARAM} indique le niveau d'indirection. Vous ne faites pas référence à PARAM, mais à la valeur stockée dans PARAM (pensez à PARAM en tant que pointeur sur value).
$ {#} augmente le nombre de paramètres (Remarque: $ 0 - le nom du script - n’est pas compté ici).
Considérez l'exécution suivante:
$./myscript.sh p1 p2 p3
Et dans le 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
Vous pouvez donc considérer $ {! #} Comme un raccourci pour l’utilisation de l’évaluation ci-dessus, qui applique exactement l’approche décrite ci-dessus - évalue la valeur stockée dans le paramètre donné, le paramètre étant 3 et contient l'argument de position $ 3
Maintenant, si vous voulez tous les paramètres sauf le dernier, vous pouvez utiliser la suppression de sous-chaîne $ {PARAM% PATTERN} où % signe signifie 'supprimez le motif correspondant le plus court à la fin de la chaîne '.
D'où dans notre script:
echo "Every parameter except the last one: ${*%${!#}}"
Vous pouvez lire quelque chose ici: Développement de paramètres
Supprimez simplement la variable length
utilisée dans la solution de Krzysztof Klimonda:
(
set -- 1 2 3 4 5
echo "${@:1:($#-1)}" # 1 2 3 4
echo "${@:(-$#):($#-1)}" # 1 2 3 4
)
Êtes-vous sûr que ce script sophistiqué est meilleur qu'un simple alias pour tar?
alias compact="tar -czvpf"
L'utilisation est:
compact ARCHIVENAME FILES...
Où les fichiers peuvent être file1 file2
ou des globes comme *.html
Autre moyen d'extraire le dernier paramètre de la liste des arguments:
eval last="\$$#"
eval set -- `awk 'BEGIN{for(i=1;i<'$#';i++) printf " \"$%d\"",i;}'`
#!/bin/bash
lastidx=$#
lastidx=`expr $lastidx - 1`
eval last='$'{$lastidx}
echo $last
Essayer:
if [ "$#" -gt '0' ]; then
/bin/echo "${!#}" "${@:1:$(($# - 1))}
fi
Ce script peut fonctionner pour vous - il renvoie une sous-gamme d'arguments et peut être appelé à partir d'un autre script.
$ 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 "$@")
#!/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
Tableau sans dernier paramètre:
array=${@:1:$#-1}
Mais c’est un bashism :(. Des solutions correctes impliqueraient un décalage et l’ajout de variables comme le font d’autres
#!/bin/sh eval last = '$' $ # while test $ # -gt 1; faire list = "$ list $ 1" shift done echo $ list $ last
Je n'arrive pas à trouver un moyen d'utiliser la notation tableau-indice sur $@
, c'est donc le mieux que je puisse faire:
#!/bin/bash
args=("$@")
echo "${args[$(($#-1))]}"