2014-09-17 10:53:12 +04:00
|
|
|
##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
## Fonctions de base: fondement
|
|
|
|
##@cooked nocomments
|
|
|
|
uprovide base.core
|
|
|
|
|
2014-09-19 14:51:19 +04:00
|
|
|
function echo_() {
|
|
|
|
# afficher la valeur $* sans passer à la ligne
|
|
|
|
echo -n "$*"
|
|
|
|
}
|
2014-09-17 10:53:12 +04:00
|
|
|
function recho() {
|
|
|
|
# afficher une valeur brute. contrairement à la commande echo, ne reconnaitre
|
|
|
|
# aucune option (i.e. -e, -E, -n ne sont pas signifiants)
|
|
|
|
if [[ "${1:0:2}" == -[eEn] ]]; then
|
|
|
|
local first="${1:1}"; shift
|
2015-05-20 16:56:50 +04:00
|
|
|
echo -n -
|
|
|
|
echo "$first" "$@"
|
2014-09-17 10:53:12 +04:00
|
|
|
else
|
|
|
|
echo "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function recho_() {
|
|
|
|
# afficher une valeur brute, sans passer à la ligne. contrairement à la commande
|
|
|
|
# echo, ne reconnaitre aucune option (i.e. -e, -E, -n ne sont pas signifiants)
|
|
|
|
if [[ "${1:0:2}" == -[eEn] ]]; then
|
|
|
|
local first="${1:1}"; shift
|
2015-05-20 16:56:50 +04:00
|
|
|
echo -n -
|
|
|
|
echo -n "$first" "$@"
|
2014-09-17 10:53:12 +04:00
|
|
|
else
|
|
|
|
echo -n "$@"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function _qval() {
|
|
|
|
# Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \`
|
|
|
|
# Cela permet de quoter une chaine à mettre entre guillements.
|
|
|
|
# Note: la protection de ! n'est pas effectuée, parce que le comportement du
|
|
|
|
# shell est incohérent entre le shell interactif et les scripts. Pour une
|
|
|
|
# version plus robuste, il est nécessaire d'utiliser un programme externe tel
|
|
|
|
# que sed ou awk
|
|
|
|
local s="$*"
|
|
|
|
s="${s//\\/\\\\}"
|
|
|
|
s="${s//\"/\\\"}"
|
|
|
|
s="${s//\$/\\\$}"
|
|
|
|
s="${s//\`/\\\`}"
|
|
|
|
recho_ "$s"
|
|
|
|
}
|
|
|
|
function should_quote() {
|
|
|
|
# Tester si la chaine $* doit être mise entre quotes
|
2015-05-20 14:15:38 +04:00
|
|
|
local s="$*"
|
|
|
|
local l="${#s}"
|
2014-12-17 11:25:17 +04:00
|
|
|
# pour optimiser, toujours mettre entre quotes une chaine vide ou de plus de 80 caractères
|
|
|
|
[ $l -eq 0 -o $l -gt 80 ] && return 0
|
|
|
|
# sinon, tester si la chaine contient des caractères spéciaux
|
2015-05-20 14:15:38 +04:00
|
|
|
s="${s//[a-zA-Z0-9]/}"
|
2014-09-17 10:53:12 +04:00
|
|
|
s="${s//,/}"
|
|
|
|
s="${s//./}"
|
|
|
|
s="${s//+/}"
|
|
|
|
s="${s//\//}"
|
|
|
|
s="${s//-/}"
|
|
|
|
s="${s//_/}"
|
|
|
|
s="${s//=/}"
|
|
|
|
[ -n "$s" ]
|
|
|
|
}
|
2014-09-19 14:51:19 +04:00
|
|
|
function qval() {
|
|
|
|
# Afficher la chaine $* quotée avec "
|
|
|
|
echo -n \"
|
|
|
|
_qval "$@"
|
|
|
|
echo \"
|
|
|
|
}
|
|
|
|
function qvalm() {
|
|
|
|
# Afficher la chaine $* quotée si nécessaire avec "
|
|
|
|
if should_quote "$*"; then
|
|
|
|
echo -n \"
|
|
|
|
_qval "$@"
|
|
|
|
echo \"
|
|
|
|
else
|
|
|
|
recho "$*"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function qvalr() {
|
2014-09-19 15:31:33 +04:00
|
|
|
# Afficher la chaine $* quotée si nécessaire avec ", sauf si elle est vide
|
|
|
|
if [ -z "$*" ]; then
|
|
|
|
:
|
|
|
|
elif should_quote "$*"; then
|
2014-09-19 14:51:19 +04:00
|
|
|
echo -n \"
|
|
|
|
_qval "$@"
|
|
|
|
echo \"
|
2014-09-19 15:31:33 +04:00
|
|
|
else
|
|
|
|
recho "$*"
|
2014-09-19 14:51:19 +04:00
|
|
|
fi
|
|
|
|
}
|
2014-09-17 10:53:12 +04:00
|
|
|
function qvals() {
|
|
|
|
# Afficher chaque argument de cette fonction quotée le cas échéant avec "
|
|
|
|
# Chaque valeur est séparée par un espace.
|
|
|
|
local arg first=1
|
|
|
|
for arg in "$@"; do
|
|
|
|
[ -z "$first" ] && echo -n " "
|
|
|
|
if should_quote "$arg"; then
|
|
|
|
echo -n \"
|
|
|
|
_qval "$arg"
|
|
|
|
echo -n \"
|
|
|
|
else
|
|
|
|
recho_ "$arg"
|
|
|
|
fi
|
|
|
|
first=
|
|
|
|
done
|
2014-09-19 14:51:19 +04:00
|
|
|
[ -z "$first" ] && echo
|
2014-09-17 10:53:12 +04:00
|
|
|
}
|
2014-12-26 16:58:58 +04:00
|
|
|
function qwc() {
|
|
|
|
# Dans la chaine $*, remplacer \ par \\, " par \", $ par \$, ` par \`, puis
|
2017-04-20 23:19:55 +04:00
|
|
|
# quoter la chaine avec ", sauf les wildcards *, ? et [class]
|
2014-12-26 16:58:58 +04:00
|
|
|
# Cela permet de quoter une chaine permettant de glober des fichiers, e.g
|
|
|
|
# eval "ls $(qwc "$value")"
|
|
|
|
# Note: la protection de ! n'est pas effectuée, parce que le comportement du
|
|
|
|
# shell est incohérent entre le shell interactif et les scripts. Pour une
|
|
|
|
# version plus robuste, il est nécessaire d'utiliser un programme externe tel
|
|
|
|
# que sed ou awk
|
|
|
|
local s="$*"
|
|
|
|
s="${s//\\/\\\\}"
|
|
|
|
s="${s//\"/\\\"}"
|
|
|
|
s="${s//\$/\\\$}"
|
|
|
|
s="${s//\`/\\\`}"
|
2017-04-20 23:19:55 +04:00
|
|
|
local r a b c
|
2014-12-26 16:58:58 +04:00
|
|
|
while [ -n "$s" ]; do
|
2017-04-20 23:19:55 +04:00
|
|
|
a=; b=; c=
|
|
|
|
a=; [[ "$s" == *\** ]] && { a="${s%%\**}"; a=${#a}; }
|
|
|
|
b=; [[ "$s" == *\?* ]] && { b="${s%%\?*}"; b=${#b}; }
|
|
|
|
c=; [[ "$s" == *\[* ]] && { c="${s%%\[*}"; c=${#c}; }
|
|
|
|
if [ -z "$a" -a -z "$b" -a -z "$c" ]; then
|
2014-12-26 16:58:58 +04:00
|
|
|
r="$r\"$s\""
|
|
|
|
break
|
|
|
|
fi
|
2017-04-20 23:19:55 +04:00
|
|
|
if [ -n "$a" ]; then
|
|
|
|
[ -n "$b" ] && [ $a -lt $b ] && b=
|
|
|
|
[ -n "$c" ] && [ $a -lt $c ] && c=
|
|
|
|
fi
|
|
|
|
if [ -n "$b" ]; then
|
|
|
|
[ -n "$a" ] && [ $b -lt $a ] && a=
|
|
|
|
[ -n "$c" ] && [ $b -lt $c ] && c=
|
|
|
|
fi
|
|
|
|
if [ -n "$c" ]; then
|
|
|
|
[ -n "$a" ] && [ $c -lt $a ] && a=
|
|
|
|
[ -n "$b" ] && [ $c -lt $b ] && b=
|
|
|
|
fi
|
|
|
|
if [ -n "$a" ]; then # PREFIX*
|
|
|
|
a="${s%%\**}"
|
|
|
|
s="${s#*\*}"
|
|
|
|
[ -n "$a" ] && r="$r\"$a\""
|
|
|
|
r="$r*"
|
|
|
|
elif [ -n "$b" ]; then # PREFIX?
|
|
|
|
a="${s%%\?*}"
|
|
|
|
s="${s#*\?}"
|
|
|
|
[ -n "$a" ] && r="$r\"$a\""
|
|
|
|
r="$r?"
|
|
|
|
elif [ -n "$c" ]; then # PREFIX[class]
|
|
|
|
a="${s%%\[*}"
|
|
|
|
b="${s#*\[}"; b="${b%%\]*}"
|
|
|
|
s="${s:$((${#a} + ${#b} + 2))}"
|
|
|
|
[ -n "$a" ] && r="$r\"$a\""
|
|
|
|
r="$r[$b]"
|
|
|
|
fi
|
2014-12-26 16:58:58 +04:00
|
|
|
done
|
|
|
|
recho_ "$r"
|
|
|
|
}
|
2014-09-17 10:53:12 +04:00
|
|
|
function qlines() {
|
|
|
|
# Traiter chaque ligne de l'entrée standard pour en faire des chaines quotées
|
|
|
|
# avec '
|
|
|
|
sed "s/'/'\\\\''/g; s/.*/'&'/g"
|
|
|
|
}
|
|
|
|
function setv() {
|
2017-03-02 02:37:47 +04:00
|
|
|
# initialiser la variable $1 avec la valeur $2..*
|
2014-09-17 10:53:12 +04:00
|
|
|
# note: en principe, la syntaxe est 'setv var values...'. cependant, la
|
|
|
|
# syntaxe 'setv var=values...' est supportée aussi
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
2014-12-17 11:25:17 +04:00
|
|
|
eval "$__s_var=\"\$*\""
|
2014-09-17 10:53:12 +04:00
|
|
|
}
|
|
|
|
function _setv() {
|
|
|
|
# Comme la fonction setv() mais ne supporte que la syntaxe '_setv var values...'
|
|
|
|
# Cette fonction est légèrement plus rapide que setv()
|
|
|
|
local __s_var="$1"; shift
|
2014-12-17 11:25:17 +04:00
|
|
|
eval "$__s_var=\"\$*\""
|
2014-09-17 10:53:12 +04:00
|
|
|
}
|
2014-09-19 15:22:55 +04:00
|
|
|
function echo_setv() {
|
|
|
|
# Afficher la commande qui serait lancée par setv "$@"
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
2014-09-19 15:31:33 +04:00
|
|
|
echo "$__s_var=$(qvalr "$*")"
|
2014-09-19 15:22:55 +04:00
|
|
|
}
|
2017-04-15 20:43:10 +04:00
|
|
|
function echo_setv2() {
|
|
|
|
# Afficher la commande qui recrée la variable $1
|
|
|
|
# Cette fonction est équivalente à echo_setv "$1=${!1}"
|
|
|
|
# Si d'autres arguments que le nom de la variable sont spécifiés, cette fonction
|
|
|
|
# se comporte comme echo_setv()
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
|
|
|
if [ $# -eq 0 ]; then
|
|
|
|
echo_setv "$__s_var" "${!__s_var}"
|
|
|
|
else
|
|
|
|
echo_setv "$__s_var" "$@"
|
|
|
|
fi
|
|
|
|
}
|
2017-03-02 02:37:47 +04:00
|
|
|
function seta() {
|
|
|
|
# initialiser le tableau $1 avec les valeurs $2..@
|
|
|
|
# note: en principe, la syntaxe est 'seta array values...'. cependant, la
|
|
|
|
# syntaxe 'seta array=values...' est supportée aussi
|
|
|
|
local __s_array="$1"; shift
|
|
|
|
if [[ "$__s_array" == *=* ]]; then
|
|
|
|
set -- "${__s_array#*=}" "$@"
|
|
|
|
__s_array="${__s_array%%=*}"
|
|
|
|
fi
|
|
|
|
eval "$__s_array=(\"\$@\")"
|
|
|
|
}
|
|
|
|
function _seta() {
|
|
|
|
# Comme la fonction seta() mais ne supporte que la syntaxe '_seta array values...'
|
|
|
|
# Cette fonction est légèrement plus rapide que seta()
|
|
|
|
local __s_array="$1"; shift
|
|
|
|
eval "$__s_array=(\"\$@\")"
|
|
|
|
}
|
|
|
|
function echo_seta() {
|
|
|
|
# Afficher la commande qui serait lancée par seta "$@"
|
2017-03-02 03:14:49 +04:00
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
|
|
|
echo "$__s_var=($(qvals "$@"))"
|
|
|
|
}
|
|
|
|
function echo_seta2() {
|
|
|
|
# Afficher la commande qui recrée le tableau $1
|
2017-04-15 20:43:10 +04:00
|
|
|
# Si d'autres arguments que le nom de tableau sont spécifiés, cette fonction se
|
|
|
|
# comporte comme echo_seta()
|
2017-03-02 02:37:47 +04:00
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
elif [ $# -eq 0 ]; then
|
|
|
|
eval "set -- \"\${$__s_var[@]}\""
|
|
|
|
fi
|
|
|
|
echo "$__s_var=($(qvals "$@"))"
|
|
|
|
}
|
2014-09-17 10:53:12 +04:00
|
|
|
function setx() {
|
|
|
|
# syntaxe 1: setx var cmd
|
|
|
|
# initialiser la variable $1 avec le résultat de la commande "$2..@"
|
|
|
|
# note: en principe, la syntaxe est 'setx var cmd args...'. cependant, la
|
|
|
|
# syntaxe 'setx var=cmd args...' est supportée aussi
|
|
|
|
# syntaxe 2: setx -a array cmd
|
|
|
|
# initialiser le tableau $1 avec le résultat de la commande "$2..@", chaque
|
|
|
|
# ligne du résultat étant un élément du tableau
|
|
|
|
# note: en principe, la syntaxe est 'setx -a array cmd args...'. cependant, la
|
|
|
|
# syntaxe 'setx -a array=cmd args...' est supportée aussi
|
|
|
|
if [ "$1" == -a ]; then
|
|
|
|
shift
|
|
|
|
local __s_array="$1"; shift
|
|
|
|
if [[ "$__s_array" == *=* ]]; then
|
|
|
|
set -- "${__s_array#*=}" "$@"
|
|
|
|
__s_array="${__s_array%%=*}"
|
|
|
|
fi
|
|
|
|
eval "$__s_array=($("$@" | qlines))"
|
|
|
|
else
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
|
|
|
eval "$__s_var="'"$("$@")"'
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function _setvx() {
|
|
|
|
# Comme la fonction setx() mais ne supporte que l'initialisation d'une variable
|
|
|
|
# scalaire avec la syntaxe '_setvx var cmd args...' pour gagner (un peu) en
|
|
|
|
# rapidité d'exécution.
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
eval "$__s_var="'"$("$@")"'
|
|
|
|
}
|
|
|
|
function _setax() {
|
|
|
|
# Comme la fonction setx() mais ne supporte que l'initialisation d'un tableau
|
|
|
|
# avec la syntaxe '_setax array cmd args...' pour gagner (un peu) en rapidité
|
|
|
|
# d'exécution.
|
|
|
|
local __s_array="$1"; shift
|
|
|
|
eval "$__s_array=($("$@" | qlines))"
|
|
|
|
}
|
|
|
|
function evalx() {
|
|
|
|
# Implémenter une syntaxe lisible et naturelle permettant d'enchainer des
|
|
|
|
# traitements sur une valeur. Par exemple, la commande
|
2015-05-20 16:56:50 +04:00
|
|
|
# evalx cmd1 [args1...] // cmd2 [args2...] // cmd3 [args3...]
|
|
|
|
# est équivalente à la commande
|
|
|
|
# cmd3 args3 "$(cmd2 args2 "$(cmd1 args1)")"
|
2014-09-17 10:53:12 +04:00
|
|
|
# Retourner le dernier code d'erreur non nul, ou 0 si toutes les commandes se
|
|
|
|
# sont exécutées sans erreur.
|
|
|
|
local __e_val __e_arg __e_r=0
|
|
|
|
local -a __e_cmd
|
|
|
|
|
|
|
|
local __e_first=1
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
__e_cmd=()
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
__e_arg="$1"; shift
|
|
|
|
[ "$__e_arg" == // ] && break
|
|
|
|
if [ "${__e_arg%//}" != "$__e_arg" ]; then
|
|
|
|
local __e_tmp="${__e_arg%//}"
|
|
|
|
if [ -z "${__e_tmp//\\/}" ]; then
|
|
|
|
__e_arg="${__e_arg#\\}"
|
|
|
|
__e_cmd=("${__e_cmd[@]}" "$__e_arg")
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
__e_cmd=("${__e_cmd[@]}" "$__e_arg")
|
|
|
|
done
|
|
|
|
|
|
|
|
if [ -n "$__e_first" ]; then
|
|
|
|
__e_val="$("${__e_cmd[@]}")" || __e_r=$?
|
|
|
|
else
|
|
|
|
__e_val="$("${__e_cmd[@]}" "$__e_val")" || __e_r=$?
|
|
|
|
fi
|
|
|
|
__e_first=
|
|
|
|
done
|
|
|
|
[ -n "$__e_val" ] && echo "$__e_val"
|
|
|
|
return $__e_r
|
|
|
|
}
|
2014-10-18 20:23:21 +04:00
|
|
|
function setxx() {
|
2014-09-17 10:53:12 +04:00
|
|
|
# équivalent à setx $1 evalx $2..@
|
|
|
|
local -a __s_args
|
|
|
|
if [ "$1" == -a ]; then __s_args=(-a); shift; fi
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
|
|
|
__s_args=("${__s_args[@]}" "$__s_var")
|
|
|
|
setx "${__s_args[@]}" evalx "$@"
|
|
|
|
}
|
|
|
|
function evalp() {
|
|
|
|
# Implémenter une syntaxe alternative permettant d'enchainer des traitements sur
|
|
|
|
# un flux de données. Par exemple, la commande
|
|
|
|
# evalp cmd1... // cmd2... // cmd3...
|
|
|
|
# affiche le résultat de la commande "$(cmd1 | cmd2 | cmd3)"
|
2017-03-01 20:01:02 +04:00
|
|
|
# Typiquement, cette fonction permet de faciliter la *construction* d'un
|
2014-09-17 10:53:12 +04:00
|
|
|
# enchainement de commandes par programme, ou de faciliter l'utilisation de la
|
|
|
|
# fonction setx() pour récupérer le résultat d'un enchainement. Dans les autres
|
|
|
|
# cas, il est plus simple et naturel d'écrire les enchainements avec la syntaxe
|
|
|
|
# de bash.
|
|
|
|
local __e_arg __e_cmd
|
|
|
|
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
__e_arg="$1"; shift
|
|
|
|
if [ "$__e_arg" == // ]; then
|
|
|
|
__e_cmd="$__e_cmd |"
|
|
|
|
continue
|
|
|
|
elif [ "${__e_arg%//}" != "$__e_arg" ]; then
|
|
|
|
local __e_tmp="${__e_arg%//}"
|
|
|
|
if [ -z "${__e_tmp//\\/}" ]; then
|
|
|
|
__e_arg="${__e_arg#\\}"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
__e_cmd="${__e_cmd:+$__e_cmd }\"$(_qval "$__e_arg")\""
|
|
|
|
done
|
|
|
|
eval "$__e_cmd"
|
|
|
|
}
|
2014-10-18 20:23:21 +04:00
|
|
|
function setxp() {
|
|
|
|
# équivalent à setx $1 evalp $2..@
|
|
|
|
local -a __s_args
|
|
|
|
if [ "$1" == -a ]; then __s_args=(-a); shift; fi
|
|
|
|
local __s_var="$1"; shift
|
|
|
|
if [[ "$__s_var" == *=* ]]; then
|
|
|
|
set -- "${__s_var#*=}" "$@"
|
|
|
|
__s_var="${__s_var%%=*}"
|
|
|
|
fi
|
|
|
|
__s_args=("${__s_args[@]}" "$__s_var")
|
|
|
|
setx "${__s_args[@]}" evalp "$@"
|
|
|
|
}
|
2014-09-17 10:53:12 +04:00
|
|
|
function testx() {
|
|
|
|
# Faire un test unaire avec la commande [ sur une valeur calculée avec evalx.
|
|
|
|
# Utiliser la syntaxe 'testx op cmds...' e.g.
|
|
|
|
# testx -z cmd1 // cmd2
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val="$(evalx "$@")"
|
|
|
|
[ $__t_op "$__t_val" ]
|
|
|
|
}
|
|
|
|
function test2x() {
|
|
|
|
# Faire une test binaire avec la commande [ entre une valeur spécifiée et une
|
|
|
|
# valeur calculée avec evalx. Utiliser la syntaxe 'test2x value op cmds...' e.g.
|
|
|
|
# test2x value == cmd1 // cmd2
|
|
|
|
local __t_val1="$1"; shift
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val2="$(evalx "$@")"
|
|
|
|
[ "$__t_val1" $__t_op "$__t_val2" ]
|
|
|
|
}
|
|
|
|
function testrx() {
|
|
|
|
# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une
|
|
|
|
# valeur calculée avec evalx. Utiliser la syntaxe 'testrx value op cmds...' e.g.
|
|
|
|
# testrx value == cmd1 // cmd2
|
|
|
|
local __t_val1="$1"; shift
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val2="$(evalx "$@")"
|
|
|
|
eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
|
|
|
|
}
|
|
|
|
function testp() {
|
|
|
|
# Faire un test unaire avec la commande [ sur une valeur calculée avec evalp.
|
|
|
|
# Utiliser la syntaxe 'testp op cmds...' e.g.
|
|
|
|
# testp -z cmd1 // cmd2
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val="$(evalp "$@")"
|
|
|
|
[ $__t_op "$__t_val" ]
|
|
|
|
}
|
|
|
|
function test2p() {
|
|
|
|
# Faire une test binaire avec la commande [ entre une valeur spécifiée et une
|
|
|
|
# valeur calculée avec evalp. Utiliser la syntaxe 'test2p value op cmds...' e.g.
|
|
|
|
# test2p value == cmd1 // cmd2
|
|
|
|
local __t_val1="$1"; shift
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val2="$(evalp "$@")"
|
|
|
|
[ "$__t_val1" $__t_op "$__t_val2" ]
|
|
|
|
}
|
|
|
|
function testrp() {
|
|
|
|
# Faire une test binaire avec la commande [[ entre une valeur spécifiée et une
|
|
|
|
# valeur calculée avec evalp. Utiliser la syntaxe 'testrp value op cmds...' e.g.
|
|
|
|
# testrp value == cmd1 // cmd2
|
|
|
|
local __t_val1="$1"; shift
|
|
|
|
local __t_op="$1"; shift
|
|
|
|
local __t_val2="$(evalp "$@")"
|
|
|
|
eval '[[ "$__t_val1" '"$__t_op"' "$__t_val2" ]]'
|
|
|
|
}
|
|
|
|
|
|
|
|
function err2out() {
|
|
|
|
# lancer la commande $@ en redirigeant la sortie d'erreur sur la sortie standard
|
|
|
|
"$@" 2>&1
|
|
|
|
}
|
2016-06-05 17:41:00 +04:00
|
|
|
|
2016-11-01 00:03:25 +04:00
|
|
|
function is_defined() {
|
|
|
|
# tester si la variable $1 est définie
|
|
|
|
[ -n "$(declare -p "$1" 2>/dev/null)" ]
|
|
|
|
}
|
|
|
|
function is_array() {
|
|
|
|
# tester si la variable $1 est un tableau
|
|
|
|
case "$(declare -p "$1" 2>/dev/null)" in declare\ -a*) return 0;; esac
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2016-06-05 17:41:00 +04:00
|
|
|
# cf http://www.fvue.nl/wiki/Bash:_Passing_variables_by_reference
|
|
|
|
function upvar() {
|
|
|
|
# Assign variable one scope above the caller
|
|
|
|
# Usage: local "$1" && upvar $1 "value(s)"
|
|
|
|
# Param: $1 Variable name to assign value to
|
|
|
|
# Param: $* Value(s) to assign. If multiple values, an array is
|
|
|
|
# assigned, otherwise a single value is assigned.
|
|
|
|
if unset -v "$1"; then
|
|
|
|
if [ $# -eq 2 ]; then
|
|
|
|
eval "$1=\"\$2\""
|
|
|
|
else
|
|
|
|
eval "$1=(\"\${@:2}\")"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
function array_upvar() {
|
|
|
|
# Comme upvar() mais force la création d'un tableau
|
|
|
|
unset -v "$1" && eval "$1=(\"\${@:2}\")"
|
|
|
|
}
|
|
|
|
function upvars() {
|
|
|
|
# Version modifiée par rapport à l'original. Il n'est plus nécessaire de
|
|
|
|
# préfixer une variable scalaire avec -v, et -a peut être spécifié sans
|
|
|
|
# argument.
|
|
|
|
# Usage:
|
|
|
|
# local varname [varname ...] && upvars [varname value] | [-aN varname [value ...]] ...
|
|
|
|
# Options:
|
|
|
|
# -a
|
|
|
|
# assigns remaining values to varname as array
|
|
|
|
# -aN
|
|
|
|
# assigns next N values to varname as array. Returns 1 if wrong number of
|
|
|
|
# options occurs
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
case "$1" in
|
|
|
|
-a)
|
|
|
|
unset -v "$2" && eval "$2=(\"\${@:3}\")"
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
-a*)
|
|
|
|
unset -v "$2" && eval "$2=(\"\${@:3:${1#-a}}\")"
|
|
|
|
shift $((${1#-a} + 2)) || return 1
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
unset -v "$1" && eval "$1=\"\$2\""
|
|
|
|
shift; shift
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
function __ab_process_pending() {
|
|
|
|
local -a values
|
|
|
|
case "$mode" in
|
|
|
|
cmd) values="$("${pending[@]}")";;
|
|
|
|
ssplit) eval "values=($("${pending[@]}"))";;
|
|
|
|
lsplit) eval "values=($("${pending[@]}" | qlines))";;
|
|
|
|
add) values=("${pending[@]}");;
|
|
|
|
esac
|
|
|
|
cmd=("${cmd[@]}" "${values[@]}")
|
|
|
|
pending=()
|
|
|
|
}
|
|
|
|
function array_buildcmd() {
|
|
|
|
# Construire un tableau dont les éléments sont calculés à partir d'une chaine
|
|
|
|
# dont les éléments sont séparés par des marqueurs ++X, e.g:
|
|
|
|
# ++ ou ++c[md] une chaine simple résultat de la commande
|
|
|
|
# ++s[split] un ensemble d'arguments résultat du split du résultat de la
|
|
|
|
# commande sur espaces
|
|
|
|
# ++l[split] un ensemble d'arguments résultat du split du résultat de la
|
|
|
|
# commande sur les lignes
|
|
|
|
# ++a[dd] un ensemble d'arguments donnés directement
|
|
|
|
# Exemple:
|
|
|
|
# array_buildcmd args echo Copie de ++ ppath "$src" ++a vers ++ ppath "$dest"
|
|
|
|
local desta="$1"; shift; local "$desta"
|
|
|
|
local mode=add
|
|
|
|
local -a pending cmd
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
case "$1" in
|
|
|
|
++c|++cmd|++) __ab_process_pending; mode=cmd;;
|
|
|
|
++s|++ssplit) __ab_process_pending; mode=ssplit;;
|
|
|
|
++l|++lsplit) __ab_process_pending; mode=lsplit;;
|
|
|
|
++a|++add) __ab_process_pending; mode=add;;
|
|
|
|
*) pending=("${pending[@]}" "$1");;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
__ab_process_pending
|
|
|
|
array_upvar "$desta" "${cmd[@]}"
|
|
|
|
}
|
|
|
|
function buildcmd() {
|
|
|
|
local -a args
|
|
|
|
array_buildcmd args "$@"
|
|
|
|
qvals "${args[@]}"
|
|
|
|
}
|
|
|
|
function evalcmd() {
|
|
|
|
local -a args
|
|
|
|
array_buildcmd args "$@"
|
|
|
|
"${args[@]}"
|
|
|
|
}
|