Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
informatique:outils:bash [2024/03/25 13:49] – [Barre de progression] bn8 | informatique:outils:bash [2024/10/30 14:07] (Version actuelle) – [Array] bn8 | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Bash ====== | ====== Bash ====== | ||
+ | |||
+ | ===== Substitution dans les variables ===== | ||
+ | |||
+ | * Chercher/ | ||
+ | * Pour chercher explicitement **au début** du contenu de la variable : '' | ||
+ | * Pour chercher explicitement **à la fin** du contenu de la variable : '' | ||
+ | * Pour remplacer **toutes les occurences** : '' | ||
+ | * Mise en **majuscule** (upper case) : '' | ||
+ | * Pour mettre **tout en majuscule** : '' | ||
+ | * Mise en **minuscule** (lower case) : '' | ||
+ | * Pour mettre **tout en minuscule** : '' | ||
===== Array ===== | ===== Array ===== | ||
- | * déclaration : '' | + | * déclaration : '' |
+ | * déclaration d'un tableau associatif : '' | ||
+ | * déclaration d'un tableau en lecture seule : '' | ||
* ajouter un élément : '' | * ajouter un élément : '' | ||
- | * lister tous les éléments : '' | + | |
- | * récupérer le nombre d'élement | + | |
+ | * lister toutes les clés d'un tableau associatif : '' | ||
+ | * récupérer le nombre d'élements d'un tableau | ||
+ | * construire un tableau à partir d'une chaîne de caractères : Cela dépend du séparateur utilisé : | ||
+ | * avec un retour à la ligne : '' | ||
+ | * avec un espace (ou autre caractère unique et " | ||
+ | * ajouter des valeurs à un tableau existant : '' | ||
+ | * ajouter depuis un fichier : '' | ||
+ | * ajouter depuis la sortie d'une commande : '' | ||
+ | * Note : voir la fonction '' | ||
==== Fonctions utiles ==== | ==== Fonctions utiles ==== | ||
Ligne 45: | Ligne 67: | ||
is_empty $array && echo empty | is_empty $array && echo empty | ||
! is_empty $array && echo not empty | ! is_empty $array && echo not empty | ||
+ | </ | ||
+ | |||
+ | === array_filter === | ||
+ | |||
+ | <code bash> | ||
+ | function array_filter() { | ||
+ | local values=() x=0 v | ||
+ | for v in " | ||
+ | if [[ " | ||
+ | x=1 | ||
+ | elif [[ $x -eq 0 ]]; then | ||
+ | values+=( " | ||
+ | else | ||
+ | mapfile -t values < <( printf ' | ||
+ | fi | ||
+ | done | ||
+ | printf ' | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Utilisation :** | ||
+ | <code bash> | ||
+ | a=(a b c d e) | ||
+ | array_filter ${a[@]} -- c e | ||
+ | # Output: | ||
+ | # a | ||
+ | # b | ||
+ | # d | ||
+ | </ | ||
+ | |||
+ | === array_intersect === | ||
+ | |||
+ | <code bash> | ||
+ | function array_intersect() { | ||
+ | local result_var=$1 | ||
+ | declare -ga " | ||
+ | shift | ||
+ | local array1=() | ||
+ | local array2=() | ||
+ | local switch_to_array2=0 | ||
+ | |||
+ | for v in " | ||
+ | if [ " | ||
+ | switch_to_array2=1 | ||
+ | elif [ $switch_to_array2 -eq 0 ]; then | ||
+ | array2+=( " | ||
+ | else | ||
+ | array1+=( " | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | for i in " | ||
+ | for j in " | ||
+ | if [[ $i == $j ]]; then | ||
+ | declare -ga " | ||
+ | break | ||
+ | fi | ||
+ | done | ||
+ | done | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Utilisation :** | ||
+ | <code bash> | ||
+ | a=(a b c d e) | ||
+ | b=(c d) | ||
+ | array_intersect c " | ||
+ | echo " | ||
+ | # Result: | ||
+ | c d | ||
</ | </ | ||
Ligne 68: | Ligne 160: | ||
# - 2 | # - 2 | ||
# - 3 | # - 3 | ||
+ | </ | ||
+ | |||
+ | === explode === | ||
+ | |||
+ | <code bash> | ||
+ | function explode() { | ||
+ | local output_var=$1 seperator=$2 | ||
+ | declare -ga " | ||
+ | mapfile -t " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Utilisation :** | ||
+ | <code bash> | ||
+ | explode myarray " " "1 2 3" "4 5" | ||
+ | declare -p myarray | ||
+ | # Output: | ||
+ | # declare -a myarray=([0]=" | ||
+ | |||
+ | explode myarray " | ||
+ | 1 | ||
+ | 2 | ||
+ | 3" | ||
+ | declare -p myarray | ||
+ | # Output: | ||
+ | # declare -a myarray=([0]=" | ||
</ | </ | ||
Ligne 74: | Ligne 192: | ||
<code bash> | <code bash> | ||
function format_duration { | function format_duration { | ||
- | | + | |
- | local D=$((T/ | + | local d=$((t/ |
- | local H=$((T/ | + | local h=$((t/ |
- | local M=$((T/60%60)) | + | local m=$((t/60%60)) |
- | local S=$((T%60)) | + | local s=$((t%60)) |
- | | + | |
- | printf ' | + | printf ' |
} | } | ||
</ | </ | ||
Ligne 173: | Ligne 291: | ||
declare -A PBARS | declare -A PBARS | ||
declare PBID | declare PBID | ||
+ | |||
+ | # Create a progress bar | ||
+ | # Arguments: | ||
+ | # - the progress bar title (default: Progress) | ||
+ | # - total count (default: 100) | ||
+ | # - bar size (default: use all the width of the terminal with a minimum of 5 caracters) | ||
+ | # - the name of the variable use to store the progress bar ID (default: PBID) | ||
function pbar_create() { | function pbar_create() { | ||
- | [ -n "$3" ] && | + | |
- | | + | local pbar_id_var=${4: |
- | ID=$( tr -dc A-Za-z0-9 </ | + | |
- | PBARS[" | + | |
- | PBARS[" | + | id="$( tr -dc A-Za-z0-9 </ |
- | PBARS[" | + | # Initialize progress bar information |
- | PBARS[" | + | PBARS[" |
- | PBARS[" | + | |
- | pbar_draw $ID | + | |
+ | | ||
+ | PBARS[" | ||
+ | PBARS[" | ||
+ | PBARS[" | ||
+ | # Draw the progress bar for a first time | ||
+ | pbar_draw | ||
} | } | ||
+ | # Finish a progress bar | ||
+ | # Arguments: | ||
+ | # - the ID of the progress bar (default: $PBID) | ||
function pbar_finish() { | function pbar_finish() { | ||
- | [ -n "$1" ] && | + | |
- | unset ' | + | |
- | unset ' | + | # Force a last update of the progess bar |
- | unset ' | + | PBARS[" |
- | unset ' | + | pbar_draw " |
- | unset ' | + | |
+ | # Unset progress bar info | ||
+ | unset ' | ||
+ | unset ' | ||
+ | unset ' | ||
+ | unset ' | ||
+ | unset ' | ||
+ | unset ' | ||
echo | echo | ||
} | } | ||
+ | # Draw the progress bar | ||
+ | # Arguments: | ||
+ | # - the ID of the progress bar (default: $PBID) | ||
+ | # - extra message to display in the progress bar (before the ETA, optional) | ||
+ | # - all extra arguments will be use to compute the extra message using printf | ||
function pbar_draw() { | function pbar_draw() { | ||
- | [ -n "$1" ] && | + | |
- | | + | |
- | | + | # Compute extra message |
- | [ $NOW -eq ${PBARS[${ID}_LAST_UPDATE]} ] && return | + | local extra=${2: |
- | let DURATION=NOW-${PBARS[${ID}_START_TIME]} | + | # shellcheck disable=SC2059 |
- | if [ ${PBARS[${ID}_CURRENT]} -gt 0 ] | + | [[ -n "$extra" |
- | | + | |
- | let TOTAL_DURATION=DURATION*${PBARS[${ID}_TOTAL]}/ | + | # Only update progress bar one time by second |
- | SPEED=$( echo " | + | local now; now=$(date +%s) |
+ | | ||
+ | |||
+ | # Compute progress percentage | ||
+ | local perc | ||
+ | (( perc=${PBARS[${id}_CURRENT]}*100/ | ||
+ | |||
+ | | ||
+ | local line line_items line_pad size line_length term_height term_width bar_done bar_pad | ||
+ | line_items=( | ||
+ | "${PBARS[${id}_TITLE]}" | ||
+ | " | ||
+ | " | ||
+ | | ||
+ | [ -n "$extra" ] && line_items+=( "- $extra" | ||
+ | |||
+ | # Add ETA (or total duration if finish) | ||
+ | if [[ "${PBARS[${id}_END_TIME]}" -eq 0 ]]; then | ||
+ | # Compute duration, total duration, ETA & speed | ||
+ | local duration total_duration speed eta | ||
+ | (( duration=now-${PBARS[${id}_START_TIME]} | ||
+ | if [[ "${PBARS[${id}_CURRENT]}" | ||
+ | (( total_duration=duration*${PBARS[${id}_TOTAL]}/ | ||
+ | speed=$( bc <<< | ||
+ | else | ||
+ | total_duration=0 | ||
+ | speed="?" | ||
+ | fi | ||
+ | (( eta=total_duration-duration )) | ||
+ | |||
+ | line_items+=( | ||
+ | "- ETA: $(format_duration $eta)" | ||
+ | "- $( printf "(%s / %s, %s/s)" " | ||
+ | | ||
else | else | ||
- | | + | |
- | | + | (( total_duration=${PBARS[${id}_END_TIME]}-${PBARS[${id}_START_TIME]} )) |
+ | | ||
fi | fi | ||
- | let ETA=TOTAL_DURATION-DURATION | ||
- | let DONE=$PERC*4/ | ||
- | let LEFT=40-$DONE | ||
- | DONE=$(printf " | ||
- | LEFT=$(printf " | ||
- | | + | |
- | " | + | # shellcheck disable=SC2034 |
- | "${DONE}" "${LEFT}" | + | read -r term_height term_width < <(stty size) |
- | ${PBARS[${ID}_CURRENT]} ${PBARS[${ID}_TOTAL]} \ | + | size=${PBARS[${id}_SIZE]} |
- | $PERC \ | + | if [[ "$size" |
- | " | + | line_length=$( wc -c <<< |
- | "$(format_duration | + | |
- | " | + | [[ $size -lt 5 ]] && size=5 |
- | $SPEED | + | fi |
+ | |||
+ | # Set progress bar text | ||
+ | (( bar_done=perc*size/ | ||
+ | (( bar_pad=size-bar_done )) | ||
+ | line_items[1]=" | ||
+ | |||
+ | # Add line padding | ||
+ | (( line_pad=term_width-${# | ||
+ | [[ $line_pad -gt 0 ]] && line_items+=( | ||
+ | |||
+ | # Compute & display line (strip the terminal width) | ||
+ | line=" | ||
+ | echo -en "\r${line: | ||
- | PBARS[${ID}_LAST_UPDATE]=$NOW | + | |
+ | | ||
} | } | ||
+ | # Increment the progress bar | ||
+ | # Arguments: | ||
+ | # - the ID of the progress bar (default: $PBID) | ||
+ | # - extra message to display in the progress bar (before the ETA, optional) | ||
+ | # - all extra arguments will be use to compute the extra message using printf | ||
function pbar_increment() { | function pbar_increment() { | ||
- | [ -n "$1" ] && | + | |
- | ((PBARS[${ID}_CURRENT]++)) | + | # Increment the progress bar state |
- | pbar_draw $ID | + | ((PBARS[${id}_CURRENT]++)) |
+ | # Draw the progress bar | ||
+ | pbar_draw | ||
} | } | ||
</ | </ | ||
Ligne 238: | Ligne 434: | ||
<code bash> | <code bash> | ||
pbar_create " | pbar_create " | ||
- | for i in $( seq 1 20 ) | + | for i in $( seq 1 20 ); do |
- | do | + | |
pbar_increment | pbar_increment | ||
sleep 0.1 | sleep 0.1 | ||
done | done | ||
pbar_finish | pbar_finish | ||
+ | </ | ||
+ | |||
+ | **Ajout d'info avant l'ETA :** | ||
+ | <code bash> | ||
+ | pbar_create " | ||
+ | for i in $( seq 1 20 ); do | ||
+ | pbar_increment "" | ||
+ | sleep 0.1 | ||
+ | done | ||
+ | pbar_finish "" | ||
</ | </ | ||
<note warning> | <note warning> |