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/06/28 16:50] – [Fonctions utiles] 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 =====
Ligne 11: Ligne 22:
   * lister toutes les clés 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[@]}''   * 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 55: Ligne 73:
 <code bash> <code bash>
 function array_filter() { function array_filter() {
-  local VALUES=() +    local values=() x=0 v 
-  local x=0 +    for v in "$@"; do 
-  for v in "$@"; do +        if [[ "$v" == "--" ]]; then 
-    if [ "$v" == "--" ]; then +            x=1 
-      x=1                +        elif [[ $x -eq 0 ]]; then 
-    elif [ $x -eq 0 ]; then +            values+=( "$v"
-      VALUES+=( "$v"  +        else 
-    else         +            mapfile -t values < <printf '%s\n' "${values[@]}" | grep -Ev "^${v}$" ) 
-      VALUES=( "${VALUES[@]#$v}" ) +        fi 
-    fi           +    done 
-  done   +    printf '%s\n' "${values[@]}"
-  printf %s "${VALUES}" "${VALUES[@]/#/$IFS}"+
 } }
 </code> </code>
Ligne 74: Ligne 91:
 a=(a b c d e) a=(a b c d e)
 array_filter ${a[@]} -- c e array_filter ${a[@]} -- c e
-# Output: a b d+# Output: 
 +a 
 +b 
 +d
 </code> </code>
  
Ligne 82: Ligne 102:
 function array_intersect() { function array_intersect() {
     local result_var=$1     local result_var=$1
-    declare -"$result_var=()"+    declare -ga "$result_var=()"
     shift     shift
     local array1=()     local array1=()
Ligne 101: Ligne 121:
         for j in "${array2[@]}"; do         for j in "${array2[@]}"; do
               if [[ $i == $j ]]; then               if [[ $i == $j ]]; then
-                    declare -"$result_var+=( \"$i\" )"+                    declare -ga "$result_var+=( \"$i\" )"
                     break                     break
               fi               fi
Ligne 113: Ligne 133:
 a=(a b c d e) a=(a b c d e)
 b=(c d) b=(c d)
-array_filter c ${a[@]} -- ${b[@]} +array_intersect "${a[@]}-- "${b[@]}" 
-echo ${c[@]}+echo "${c[@]}"
 # Result: # Result:
 c d c d
Ligne 140: 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 146: 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 254: Ligne 300:
 function pbar_create() { function pbar_create() {
     # Define the name of the variable that will store the progress bar ID     # Define the name of the variable that will store the progress bar ID
-    [ -"$4" ] && PBAR_ID_VAR="$4" || PBAR_ID_VAR=PBID +    local pbar_id_var=${4:-}; [[ -"$pbar_id_var]] && pbar_id_var=PBID 
-    declare -n ID="$PBAR_ID_VAR"+    local -n id="$pbar_id_var"
     # Generate the progress bar ID     # Generate the progress bar ID
-    ID=$( tr -dc A-Za-z0-9 </dev/urandom | head -c 3 )+    id="$( tr -dc A-Za-z0-9 </dev/urandom | head -c 3 )"
     # Initialize progress bar information     # Initialize progress bar information
-    PBARS["${ID}_START_TIME"]="$( date +%s )" +    PBARS["${id}_START_TIME"]="$( date +%s )" 
-    [ -n "$1" ] && PBARS["${ID}_TITLE"]="$1" || PBARS["${ID}_TITLE"]="Progress" +    [ -n "$1" ] && PBARS["${id}_TITLE"]="$1" || PBARS["${id}_TITLE"]="Progress" 
-    [ -n "$2" ] && PBARS["${ID}_TOTAL"]="$2" || PBARS["${ID}_TOTAL"]=100 +    [ -n "$2" ] && PBARS["${id}_TOTAL"]="$2" || PBARS["${id}_TOTAL"]=100 
-    [ -n "$3" ] && PBARS["${ID}_SIZE"]="$3" || PBARS["${ID}_SIZE"]=0 +    [ -n "$3" ] && PBARS["${id}_SIZE"]="$3" || PBARS["${id}_SIZE"]=0 
-    PBARS["${ID}_CURRENT"]=0 +    PBARS["${id}_CURRENT"]=0 
-    PBARS["${ID}_LAST_UPDATE"]=0+    PBARS["${id}_LAST_UPDATE"]=0 
 +    PBARS["${id}_END_TIME"]=0
     # Draw the progress bar for a first time     # Draw the progress bar for a first time
-    pbar_draw $ID+    pbar_draw "$id"
 } }
  
Ligne 273: Ligne 320:
 # - the ID of the progress bar (default: $PBID) # - 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
 } }
Ligne 286: Ligne 340:
 # - the ID of the progress bar (default: $PBID) # - the ID of the progress bar (default: $PBID)
 # - extra message to display in the progress bar (before the ETA, optional) # - 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() {
-    [ -"$1" ] && ID=$1 || ID=$PBID+    local id=${1:-}; [[ -"$id]] && id=$PBID 
 + 
 +    # Compute extra message 
 +    local extra=${2:-} 
 +    # shellcheck disable=SC2059 
 +    [[ -n "$extra" ]] && [[ $# -gt 2 ]] && extra=$( printf "$extra" "${@:3}" )
  
     # Only update progress bar one time by second     # Only update progress bar one time by second
-    NOW=$(date +%s) +    local now; now=$(date +%s) 
-    [ $NOW -eq ${PBARS[${ID}_LAST_UPDATE]} ] && return+    [[ "${PBARS[${id}_END_TIME]}" -eq 0 ]] && [[ $now -eq ${PBARS[${id}_LAST_UPDATE]} ]] && return
  
     # Compute progress percentage     # Compute progress percentage
-    let PERC=${PBARS[${ID}_CURRENT]}*100/${PBARS[${ID}_TOTAL]} +    local perc 
- +    (( perc=${PBARS[${id}_CURRENT]}*100/${PBARS[${id}_TOTAL]} ))
-    # Compute duration, total duration, ETA & speed +
-    let DURATION=NOW-${PBARS[${ID}_START_TIME]} +
-    if [ ${PBARS[${ID}_CURRENT]} -gt 0 ] +
-    then +
-        let TOTAL_DURATION=DURATION*${PBARS[${ID}_TOTAL]}/${PBARS[${ID}_CURRENT]} +
-        SPEED=$( echo "scale=1; ${PBARS[${ID}_CURRENT]}/$DURATION"|bc ) +
-    else +
-        TOTAL_DURATION=0 +
-        SPEED="?" +
-    fi +
-    let ETA=TOTAL_DURATION-DURATION+
  
     # Compute line without the progress bar     # Compute line without the progress bar
-    LINE=( +    local line line_items line_pad size line_length term_height term_width bar_done bar_pad 
-        "${PBARS[${ID}_TITLE]}"+    line_items=( 
 +        "${PBARS[${id}_TITLE]}"
         "[]"         "[]"
-        "${PBARS[${ID}_CURRENT]}/${PBARS[${ID}_TOTAL]} (${PERC}%)" +        "${PBARS[${id}_CURRENT]}/${PBARS[${id}_TOTAL]} (${perc}%)"
-    ) +
-    [ -n "$2" ] && LINE+=( "- $2" ) +
-    LINE+=( +
-        "- ETA: $(format_duration $ETA)" +
-        "- $( printf "(%s / %s, %s/s)" "$(format_duration $DURATION)" "$(format_duration $TOTAL_DURATION)" $SPEED )"+
     )     )
 +    [ -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
 +        local total_duration
 +        (( total_duration=${PBARS[${id}_END_TIME]}-${PBARS[${id}_START_TIME]} ))
 +        line_items+=( "- Total duration: $(format_duration $total_duration)" )
 +    fi
  
     # Compute progress bar length (if not configured)     # Compute progress bar length (if not configured)
-    read -r TERM_HEIGHT TERM_WIDTH < <(stty size) +    # shellcheck disable=SC2034 
-    SIZE=${PBARS[${ID}_SIZE]} +    read -r term_height term_width < <(stty size) 
-    if [ $SIZE -eq 0 ] +    size=${PBARS[${id}_SIZE]} 
-    then +    if [[ "$size" -eq 0 ]]; then 
-        LINE_LENGTH=$( echo "${LINE[*]}"|wc -c +        line_length=$( wc -c <<< "${line_items[*]}" ) 
-        SIZE=$[ $TERM_WIDTH $LINE_LENGTH ] +        (( size=term_width-line_length )) 
-        [ $SIZE -lt 5 ] && SIZE=5+        [[ $size -lt 5 ]] && size=5
     fi     fi
  
     # Set progress bar text     # Set progress bar text
-    let DONE=$PERC*$SIZE/100 +    (( bar_done=perc*size/100 )) 
-    let LEFT=$SIZE-$DONE +    (( bar_pad=size-bar_done )) 
-    LINE[1]="[$(printf "%${DONE}s"|tr ' ' '#')$(printf "%${LEFT}s"|tr ' ' '-')]"+    line_items[1]="[$(printf "%${bar_done}s"|tr ' ' '#')$(printf "%${bar_pad}s"|tr ' ' '-')]"
  
     # Add line padding (if need)     # Add line padding (if need)
-    let LINE_PAD=TERM_WIDTH-${#LINE+    (( line_pad=term_width-${#line_items)) 
-    [ $LINE_PAD -gt 0 ] && LINE+=( "$(printf "%${LINE_PAD}s")" )+    [[ $line_pad -gt 0 ]] && line_items+=( "$(printf "%${line_pad}s")" )
  
     # Compute & display line (strip the terminal width)     # Compute & display line (strip the terminal width)
-    LINE="${LINE[*]}" +    line="${line_items[*]}" 
-    echo -en "\r${LINE:0:$TERM_WIDTH}"+    echo -en "\r${line:0:$term_width}"
  
     # Update last progress bar update time     # Update last progress bar update time
-    PBARS[${ID}_LAST_UPDATE]=$NOW+    PBARS[${id}_LAST_UPDATE]=$now
 } }
  
Ligne 353: Ligne 423:
 # - all extra arguments will be use to compute the extra message using printf # - all extra arguments will be use to compute the extra message using printf
 function pbar_increment() { function pbar_increment() {
-    [ -n "$1" ] && ID=$1 || ID=$PBID +    local id=${1:-}; [[ -"$id" ]] && id=$PBID
-    # Compute extra message +
-    if [ -"$2" ] +
-    then +
-        EXTRA="$2" +
-        shift 2 +
-        [ $# -gt 0 ] && EXTRA=$( printf "$EXTRA" "$@"+
-    else +
-        EXTRA="" +
-    fi+
     # Increment the progress bar state     # Increment the progress bar state
-    ((PBARS[${ID}_CURRENT]++))+    ((PBARS[${id}_CURRENT]++))
     # Draw the progress bar     # Draw the progress bar
-    pbar_draw $ID "$EXTRA"+    pbar_draw "$@"
 } }
 </code> </code>
Ligne 373: 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.1719593432.txt.gz
  • Dernière modification : 2024/06/28 16:50
  • de bn8