informatique:outils:bash

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

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] bn8informatique:outils:bash [2024/10/30 14:07] (Version actuelle) – [Array] bn8
Ligne 1: Ligne 1:
 ====== Bash ====== ====== Bash ======
 +
 +===== Substitution dans les variables =====
 +
 +  * Chercher/remplacer : ''${variable/search_pattern/replacement}'' => remplacer la première occurrence de ''search_pattern'' par ''replacement'' dans de contenu de la variable ''variable''.
 +    * Pour chercher explicitement **au début** du contenu de la variable : ''${parameter/#search_pattern/replacement}''
 +    * Pour chercher explicitement **à la fin** du contenu de la variable : ''${parameter/%search_pattern/replacement}''
 +    * Pour remplacer **toutes les occurences** : ''%%${parameter//search_pattern/replacement}%%''
 +  * Mise en **majuscule** (upper case) : ''${variable^}'' => mise en majuscule du première caractère du contenu de la variable ''variable''
 +    * Pour mettre **tout en majuscule** : ''${variable^^}''
 +  * Mise en **minuscule** (lower case) : ''${variable,}'' => mise en minuscule du première caractère du contenu de la variable ''variable''
 +    * Pour mettre **tout en minuscule** : ''${variable,,}''
  
 ===== Array ===== ===== Array =====
  
-  * déclaration : ''array=( 1 2 3 )''+  * déclaration : ''array=( 1 2 3 )'' ou ''declare -a array=( 1 2 3 )'' 
 +  * déclaration d'un tableau associatif : ''declare -A array=( ['key1']='value1' ['key2']='value2' ['key3']='value3' )'' 
 +  * déclaration d'un tableau en lecture seule : ''declare -Ar ro_array=( [...] )'' ou ''declare -ar ro_array=( [...] )''
   * ajouter un élément : ''array+=( 4 )''   * ajouter un élément : ''array+=( 4 )''
-  * lister tous les éléments : ''echo "${array[@]}"'' +  * ajouter un élément à un tableau associatif : ''array+=( ['key']='value' )'' 
-  * récupérer le nombre d'élement : ''echo ${#array[@]}''+  * lister tous les éléments d'un tableau (=valeur dans le cas d'un tableau associatif) : ''${array[@]}'' 
 +  * lister toutes les clés d'un tableau associatif : ''${!array[@]}'' 
 +  * récupérer le nombre d'élements d'un tableau : ''echo ${#array[@]}'' 
 +  * construire un tableau à partir d'une chaîne de caractères : Cela dépend du séparateur utilisé : 
 +    * avec un retour à la ligne : ''%%mapfile -t myarray <<< "$ALL"%%'' 
 +    * avec un espace (ou autre caractère unique et "simple) : ''%%IFS=" " read -ra myarray <<< "$ALL"%%'' 
 +    * ajouter des valeurs à un tableau existant : ''%%mapfile -t -O "${#myarray[@)}" myarray <<< "$ALL"%%'' 
 +    * ajouter depuis un fichier : ''%%mapfile -t myarray < /path/to/file%%'' 
 +    * ajouter depuis la sortie d'une commande : ''%%mapfile -t myarray < <( grep -vE '^#' /path/to/file | grep -vE '^\s*$' )%%'' 
 +    * Note : voir la fonction ''explode'' pour une version générique
  
 ==== 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
 +</code>
 +
 +=== array_filter ===
 +
 +<code bash>
 +function array_filter() {
 +    local values=() x=0 v
 +    for v in "$@"; do
 +        if [[ "$v" == "--" ]]; then
 +            x=1
 +        elif [[ $x -eq 0 ]]; then
 +            values+=( "$v" )
 +        else
 +            mapfile -t values < <( printf '%s\n' "${values[@]}" | grep -Ev "^${v}$" )
 +        fi
 +    done
 +    printf '%s\n' "${values[@]}"
 +}
 +</code>
 +
 +**Utilisation :**
 +<code bash>
 +a=(a b c d e)
 +array_filter ${a[@]} -- c e
 +# Output:
 +# a
 +# b
 +# d
 +</code>
 +
 +=== array_intersect ===
 +
 +<code bash>
 +function array_intersect() {
 +    local result_var=$1
 +    declare -ga "$result_var=()"
 +    shift
 +    local array1=()
 +    local array2=()
 +    local switch_to_array2=0
 +
 +    for v in "$@"; do
 +        if [ "$v" == "--" ]; then
 +            switch_to_array2=1
 +        elif [ $switch_to_array2 -eq 0 ]; then
 +            array2+=( "$v" )
 +        else
 +            array1+=( "$v" )
 +        fi
 +    done
 +
 +    for i in "${array1[@]}"; do
 +        for j in "${array2[@]}"; do
 +              if [[ $i == $j ]]; then
 +                    declare -ga "$result_var+=( \"$i\" )"
 +                    break
 +              fi
 +        done
 +    done
 +}
 +</code>
 +
 +**Utilisation :**
 +<code bash>
 +a=(a b c d e)
 +b=(c d)
 +array_intersect c "${a[@]}" -- "${b[@]}"
 +echo "${c[@]}"
 +# Result:
 +c d
 </code> </code>
  
Ligne 68: Ligne 160:
 # - 2 # - 2
 # - 3 # - 3
 +</code>
 +
 +=== explode ===
 +
 +<code bash>
 +function explode() {
 +    local output_var=$1 seperator=$2
 +    declare -ga "$output_var=()"
 +    mapfile -t "$output_var" < <( tr "$seperator" '\n' <<< "${@:3}" | grep -v '^$' )
 +}
 +</code>
 +
 +**Utilisation :**
 +<code bash>
 +explode myarray " " "1 2 3" "4 5"
 +declare -p myarray
 +# Output:
 +# declare -a myarray=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6")
 +
 +explode myarray "\n" "
 +1
 +2
 +3"
 +declare -p myarray
 +# Output:
 +# declare -a myarray=([0]="1" [1]="2" [2]="3")
 </code> </code>
  
Ligne 74: Ligne 192:
 <code bash> <code bash>
 function format_duration { function format_duration {
-  local T=$1 +    local t=$1 
-  local D=$((T/60/60/24)) +    local d=$((t/60/60/24)) 
-  local H=$((T/60/60%24)) +    local h=$((t/60/60%24)) 
-  local M=$((T/60%60)) +    local m=$((t/60%60)) 
-  local S=$((T%60)) +    local s=$((t%60)) 
-  (( $D > )) && printf '%d days and ' $D +    [[ $d -gt ]] && printf '%d days and ' $d 
-  printf '%02d:%02d:%02d' $$$S+    printf '%02d:%02d:%02d' $$$s
 } }
 </code> </code>
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() {
-    [ -"$3" ] && PBAR_ID_VAR="$3" || PBAR_ID_VAR=PBID +    # Define the name of the variable that will store the progress bar ID 
-    declare -n ID="$PBAR_ID_VAR+    local pbar_id_var=${4:-}; [[ -"$pbar_id_var]] && pbar_id_var=PBID 
-    ID=$( tr -dc A-Za-z0-9 </dev/urandom | head -c 3 ) +    local -n id="$pbar_id_var
-    PBARS["${ID}_START_TIME"]="$( date +%s )" +    # Generate the progress bar ID 
-    PBARS["${ID}_TITLE"]="$1" +    id="$( tr -dc A-Za-z0-9 </dev/urandom | head -c 3 )
-    PBARS["${ID}_TOTAL"]="$2" +    # Initialize progress bar information 
-    PBARS["${ID}_CURRENT"]=0 +    PBARS["${id}_START_TIME"]="$( date +%s )" 
-    PBARS["${ID}_LAST_UPDATE"]=0 +    [ -n "$1" ] && PBARS["${id}_TITLE"]="$1" || PBARS["${id}_TITLE"]="Progress
-    pbar_draw $ID+    [ -n "$2" ] && PBARS["${id}_TOTAL"]="$2" || PBARS["${id}_TOTAL"]=100 
 +    [ -n "$3" ] && PBARS["${id}_SIZE"]="$3" || PBARS["${id}_SIZE"]=0 
 +    PBARS["${id}_CURRENT"]=0 
 +    PBARS["${id}_LAST_UPDATE"]=0 
 +    PBARS["${id}_END_TIME"]=0 
 +    # Draw the progress bar for a first time 
 +    pbar_draw "$id"
 } }
  
 +# Finish a progress bar
 +# Arguments:
 +# - the ID of the progress bar (default: $PBID)
 function pbar_finish() { function pbar_finish() {
-    [ -"$1" ] && ID=$1 || ID=$PBID +    local id=${1:-}; [[ -"$id]] && id=$PBID 
-    unset 'PBARS[${ID}_START_TIME]' + 
-    unset 'PBARS[${ID}_TITLE]' +    # Force a last update of the progess bar 
-    unset 'PBARS[${ID}_TOTAL]' +    PBARS["${id}_END_TIME"]="$( date +%s )" 
-    unset 'PBARS[${ID}_CURRENT]' +    pbar_draw "$@" 
-    unset 'PBARS[${ID}_LAST_UPDATE]'+ 
 +    # Unset progress bar info 
 +    unset 'PBARS[${id}_START_TIME]' 
 +    unset 'PBARS[${id}_TITLE]' 
 +    unset 'PBARS[${id}_TOTAL]' 
 +    unset 'PBARS[${id}_CURRENT]' 
 +    unset 'PBARS[${id}_LAST_UPDATE]' 
 +    unset 'PBARS[${id}_END_TIME]'
     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" ] && ID=$1 || ID=$PBID +    local id=${1:-}; [[ -z "$id" ]] && id=$PBID 
-    let PERC=${PBARS[${ID}_CURRENT]}*100/${PBARS[${ID}_TOTAL]} + 
-    NOW=$(date +%s+    # 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]] && [[ $# -gt 2 ]] && extra=$( printf "$extra" "${@:3}"
-    then + 
-        let TOTAL_DURATION=DURATION*${PBARS[${ID}_TOTAL]}/${PBARS[${ID}_CURRENT]} +    # Only update progress bar one time by second 
-        SPEED=$( echo "scale=1; ${PBARS[${ID}_CURRENT]}/$DURATION"|bc )+    local now; now=$(date +%s) 
 +    [[ "${PBARS[${id}_END_TIME]}" -eq 0 ]] && [[ $now -eq ${PBARS[${id}_LAST_UPDATE]} ]] && return 
 + 
 +    # Compute progress percentage 
 +    local perc 
 +    (( perc=${PBARS[${id}_CURRENT]}*100/${PBARS[${id}_TOTAL]} )) 
 + 
 +    # Compute line without the progress bar 
 +    local line line_items line_pad size line_length term_height term_width bar_done bar_pad 
 +    line_items=
 +        "${PBARS[${id}_TITLE]}" 
 +        "[]" 
 +        "${PBARS[${id}_CURRENT]}/${PBARS[${id}_TOTAL]} (${perc}%)" 
 +    
 +    [ -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]}-gt 0 ]]; then 
 +            (( total_duration=duration*${PBARS[${id}_TOTAL]}/${PBARS[${id}_CURRENT]} )) 
 +            speed=$( bc <<< "scale=1; ${PBARS[${id}_CURRENT]}/$duration
 +        else 
 +            total_duration=0 
 +            speed="?" 
 +        fi 
 +        (( eta=total_duration-duration )) 
 + 
 +        line_items+=( 
 +            "- ETA: $(format_duration $eta)" 
 +            "- $( printf "(%s / %s, %s/s)" "$(format_duration $duration)" "$(format_duration $total_duration)" "$speed" )" 
 +        )
     else     else
-        TOTAL_DURATION=0 +        local total_duration 
-        SPEED="?"+        (( total_duration=${PBARS[${id}_END_TIME]}-${PBARS[${id}_START_TIME]} )) 
 +        line_items+="- Total duration: $(format_duration $total_duration))
     fi     fi
-    let ETA=TOTAL_DURATION-DURATION 
-    let DONE=$PERC*4/10 
-    let LEFT=40-$DONE 
-    DONE=$(printf "%${DONE}s"|tr ' ' '#') 
-    LEFT=$(printf "%${LEFT}s"|tr ' ' '-') 
  
-    printf "\r%s: [%s%s] %d/%d - %d%% - ETA: %s (%s / %s, %s/s)" \ +    # Compute progress bar length (if not configured) 
-        "${PBARS[${ID}_TITLE]}" \ +    # 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-eq 0 ]]; then 
-        "$(format_duration $ETA)" \ +        line_length=$( wc -c <<< "${line_items[*]}" ) 
-        "$(format_duration $DURATION)" \ +        (( size=term_width-line_length )) 
-        "$(format_duration $TOTAL_DURATION)" \ +        [[ $size -lt 5 ]] && size=5 
-        $SPEED+    fi 
 + 
 +    # Set progress bar text 
 +    (( bar_done=perc*size/100 )) 
 +    (( bar_pad=size-bar_done )) 
 +    line_items[1]="[$(printf "%${bar_done}s"|tr ' ' '#')$(printf "%${bar_pad}s"|tr ' ' '-')]" 
 + 
 +    # Add line padding (if need) 
 +    (( line_pad=term_width-${#line_items} )
 +    [[ $line_pad -gt 0 ]] && line_items+=( "$(printf "%${line_pad}s")" ) 
 + 
 +    # Compute & display line (strip the terminal width) 
 +    line="${line_items[*]}
 +    echo -en "\r${line:0:$term_width}"
  
-    PBARS[${ID}_LAST_UPDATE]=$NOW+    # Update last progress bar update time 
 +    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() {
-    [ -"$1" ] && ID=$1 || ID=$PBID +    local id=${1:-}; [[ -"$id]] && id=$PBID 
-    ((PBARS[${ID}_CURRENT]++)) +    # Increment the progress bar state 
-    pbar_draw $ID+    ((PBARS[${id}_CURRENT]++)) 
 +    # Draw the progress bar 
 +    pbar_draw "$@"
 } }
 </code> </code>
Ligne 238: Ligne 434:
 <code bash> <code bash>
 pbar_create "Test" 20 pbar_create "Test" 20
-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
 +</code>
 +
 +**Ajout d'info avant l'ETA :**
 +<code bash>
 +pbar_create "Test" 20
 +for i in $( seq 1 20 ); do
 +    pbar_increment "" "%d iteration(s) - %d found(s)" $i $(( i/2 ))
 +    sleep 0.1
 +done
 +pbar_finish "" "%d iteration(s) - %d found(s)" $i $(( i/2 ))
 </code> </code>
  
 <note warning>La fonction [[#format_duration]] est nécessaire.</note> <note warning>La fonction [[#format_duration]] est nécessaire.</note>
  • informatique/outils/bash.1711374594.txt.gz
  • Dernière modification : 2024/03/25 13:49
  • de bn8