Bash: trucs et astuces : Différence entre versions

De TechWik
Aller à : navigation, rechercher
m (Utiliser les expressions régulières directement dans le shell)
m (Conversions)
Ligne 1 : Ligne 1 :
 
== Fonctions utiles ==
 
== Fonctions utiles ==
 
=== Conversions ===
 
=== Conversions ===
  # conversion netmask => cidr
+
==== conversion netmask => cidr ====
  # ex: mask2cidr 255.255.128.0 --> 17
+
Exemple: mask2cidr 255.255.128.0 --> 17
 
   # suppose qu'il n'y a plus de "255." après un octet non-255
 
   # suppose qu'il n'y a plus de "255." après un octet non-255
 
   mask2cidr ()
 
   mask2cidr ()
Ligne 12 : Ligne 12 :
 
   }
 
   }
  
  # conversion cidr => netmask  
+
==== conversion cidr => netmask ====
  # ex: cidr2mask 17 --> 255.255.128.0
+
Exemple: cidr2mask 17 --> 255.255.128.0
 
   cidr2mask ()
 
   cidr2mask ()
 
   {
 
   {
Ligne 19 : Ligne 19 :
 
     [ $1 -gt 1 ] && shift $1 || shift
 
     [ $1 -gt 1 ] && shift $1 || shift
 
     echo ${1-0}.${2-0}.${3-0}.${4-0}
 
     echo ${1-0}.${2-0}.${3-0}.${4-0}
 +
  }
 +
 +
==== expansion IPv6 ====
 +
Exemple: expand_ip6 fe80::68c8:c7b1:3199:f4b  --> fe80:0000:0000:0000:68c8:c7b1:3199:0f4b
 +
  expand_ip6() {
 +
    ip6=$1
 +
    IFS=: ff=($ip6); unset IFS
 +
    res=""
 +
    let ix=0
 +
    nf=${#ff[*]}
 +
    while [ $ix -lt $nf ]; do
 +
      it=${ff[ix]}
 +
      if [ ${#it} -gt 0 ]; then
 +
        let n=4-${#it};
 +
        while [ $n -gt 0 ]; do it="0${it}"; let n=n-1;done ;
 +
      else
 +
        let n=8-$nf;
 +
        it="0000";
 +
        while [ $n -gt 0 ]; do it="${it}:0000"; let n=n-1;done ;
 +
      fi;
 +
      if [ -z "$res" ];then
 +
        res=$it;
 +
      else
 +
        res="${res}:${it}";
 +
      fi
 +
      let ix=ix+1
 +
    done
 +
    echo $res
 +
  }
 +
 +
==== compression IPv6 ====
 +
Exemple: compress_ip6 fe80:0000:0000:0000:68c8:c7b1:3199:0f4b  --> fe80::68c8:c7b1:3199:f4b 
 +
  compress_ip6() {
 +
    ip6=$1
 +
    echo $ip6 | sed -r -e 's/:0+/:0/g' -e 's/:(0:){2,8}/::/' -e 's/:0([1-9a-f])/:\1/g'
 
   }
 
   }
  

Version du 28 juillet 2018 à 14:56

Fonctions utiles

Conversions

conversion netmask => cidr

Exemple: mask2cidr 255.255.128.0 --> 17

 # suppose qu'il n'y a plus de "255." après un octet non-255
 mask2cidr ()
 {
   local x=${1##*255.}
   set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
   x=${1%%$3*}
   echo $(( $2 + (${#x}/4) ))
 }

conversion cidr => netmask

Exemple: cidr2mask 17 --> 255.255.128.0

 cidr2mask ()
 {
   set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
   [ $1 -gt 1 ] && shift $1 || shift
   echo ${1-0}.${2-0}.${3-0}.${4-0}
 }

expansion IPv6

Exemple: expand_ip6 fe80::68c8:c7b1:3199:f4b --> fe80:0000:0000:0000:68c8:c7b1:3199:0f4b

 expand_ip6() {
   ip6=$1
   IFS=: ff=($ip6); unset IFS
   res=""
   let ix=0
   nf=${#ff[*]}
   while [ $ix -lt $nf ]; do 
     it=${ff[ix]}
     if [ ${#it} -gt 0 ]; then 
       let n=4-${#it}; 
       while [ $n -gt 0 ]; do it="0${it}"; let n=n-1;done ; 
     else 
       let n=8-$nf; 
       it="0000"; 
       while [ $n -gt 0 ]; do it="${it}:0000"; let n=n-1;done ; 
     fi; 
     if [ -z "$res" ];then 
       res=$it; 
     else 
       res="${res}:${it}";
     fi
     let ix=ix+1 
   done
   echo $res
 }

compression IPv6

Exemple: compress_ip6 fe80:0000:0000:0000:68c8:c7b1:3199:0f4b --> fe80::68c8:c7b1:3199:f4b

 compress_ip6() {
   ip6=$1
   echo $ip6 | sed -r -e 's/:0+/:0/g' -e 's/:(0:){2,8}/::/' -e 's/:0([1-9a-f])/:\1/g'
 }

manipuler des chaines de caractères

split chaine de caracteres:

 1)IFS:
   OIFS=$IFS
   string="ABCDE-123456"
   IFS=- # use "local IFS=-" inside the function
   set $string
   echo $1 # >>> ABCDE
   echo $2 # >>> 123456
   IFS=$OIFS     # restituer le séparateur originel
 2) récupérer le début ou la fin (ici separateur = ' ' )
   line="myhost 192.168.1.145 abcdefg 123456"
   # enlever le dernier champ
   $ echo ${line% *}
   myhost 192.168.1.145 abcdefg
   # conserver le premier champ
   $ echo ${line%% *}
   myhost
   # enlever le premier champ
   $ echo ${line#* }
   192.168.1.145 abcdefg 123456
   # conserver le dernier champ
   $ echo ${line##* }
   123456
 3) affecter les différents termes d'une ligne (cf IFS) à un tableau
   line="myhost 192.168.1.145 is a good host"
   $ termes=($line)
   $ echo ${termes[0]}
   myhost
   $ echo ${termes[4]}
   good

substring

 Par exemple:
  $ date=2017-01-12
  $ echo ${date:5:2}
  
 résultat: "01"

Utiliser les expressions régulières directement dans le shell

Avec l'opérateur =~ , par exemple:

 regex="([0-9]+)[[:space:]](.*)"
  file="02 Rumour Has It.wma"
  if [[ $file =~ $regex ]]; then
    echo "matched:(${BASH_REMATCH[1]}) -> ${BASH_REMATCH[2]}"
  fi

récupérer le resultat d'une commande dans un tableau, ligne à ligne

 1) IFS:
   $ IFS=$'\r\n'
   $ aa=($(grep blabla /pathtofile))
   $ echo ${aa[0]}
     ici ma premiere ligne. 
   
   manipuler le tableau:
   for str in "${aa[@]}";do echo $str;done;
 2) read: il faut passer par un fichier intermédiaire
   $ grep blabla /pathtofile > /tmp/out
   $ while read str; do echo $str;done < /tmp/out

manipuler des variables

 # variable avec valeur par defaut
   if [ ${var:=n} = "y" ]; then ... 
   => affecte 'n' par défaut à $var.

manipuler les lignes d'un fichier: exemple conversion d'un dossier mp3 => wav

 # chercher lister les fichiers mp3 
 find . -name "*.mp3"  > /tmp/lst
 # lire la liste dans un tableau (1 enregistrement par ligne)
 IFS=$'\n' read -d  -r -a files < /tmp/lst
 while [ $i -lt ${#files[@]} ]; do
   fout=` echo ${files[$i]} | sed "s/.mp3/.wav/"`; 
   lame --decode "${files[$i]}" "../wav/$fout";
   let i=i+1;
 done

Modifier quelques comportements avec shopt

SSH et les alias

Les alias ne sont développés qu'avec les shells interactifs sauf si l'option expand_aliases du shell est activée par la commande shopt. Pour utiliser des alias distants en SSH, ajouter dans .bashrc de l'utilisateur distant:

 if [ -z "$PS1" ]; then
   shopt -s expand_aliases
 fi

avec cdable_vars interpréter les variables pour la commande 'cd'

Si cette option est active, un argument de la commande interne cd qui n'est pas un répertoire est supposé être un nom de variable dont la valeur est le répertoire visé. Exemple:

 $ shopt -s cdable_vars  
 $ vms=/home/VMimages
 $ cd vms
 /home/VMimages

avec nocaseglob ignorer la casse pour développer les noms de fichiers

Si cette option est active, bash traite les noms de fichiers sans différences minuscules/majuscules lors du développement des noms de fichiers

 $ shopt -s nocaseglob  
 $ ls cis*
 CIS_Red_Hat_Enterprise_Linux_6_Benchmark_v1.4.0-oval.xml  CIS_Red_Hat_Enterprise_Linux_6_Benchmark_v1.4.0-xccdf.xml

Comportement / syntaxe bash

Grouper des commandes

  • avec () les commandes placées dans la liste entre parenthèses sont exécutées dans un sous-shell. Il n'y a pas persistence dans le shell courant des variables manipulées dans ces commandes.
  • avec {} les commandes placées entre accolades sont exécutées dans le contexte de shell courant. Le point virgule séparant les commandes est obligatoire sur la dernière, ainsi que les espaces autour de début et fin de bloc. D'éventuelles redirections peuvent être appliquées au bloc de commandes. Par exemple, lire un fichier dans une variable, et éviter les messages d'erreur:
 { var=$(<"$file"); } 2>/dev/null;

Manipuler l'historique

  • Répéter la dernière commande : !!
  • Répéter la dernière commande commançant par un motif:
   $ !echo
   echo Bash Shortcuts
   Bash Shortcuts

et avec ":p" afficher la dernière commande commançant par un motif sans l'exécuter (mais l'exécuter ensuite avec !!):

   $ echo Bash Shortcuts
   Bash Shortcuts
   $ wc -m /etc/bash_completion
   45 /etc/bash_completion
   $ !echo:p
   echo Bash Shortcuts
   $ !!
   echo Bash Shortcuts
   Bash Shortcuts
  • Rappeler les arguments de la dernière commande (tous : !* , le premier: !^ , le dernier: !$ ).
   $ echo First Bash Shortcuts arg is not last
   First Bash Shortcuts arg is not last
   $ touch !*
   touch First Bash Shortcuts arg is not last
   $ ls
   First Bash Shortcuts arg is not last ... 
   $ rm First Bash Shortcuts arg is not last
   $ echo !^
   First
   $ echo First Bash Shortcuts arg is not last
   $ touch !*
   touch last
  • Rappeler la dernière commande avec substitution d'une partie
   $ echo this is our args
   this is our args
   $ ^our args^my last word^
   echo this is my last word 
   this is my last word
  • Rappeler une commande avec substitution
   $ localectl list-keymaps |grep "^fr"
   ...
   $ ls
   ... 
   $ !locale:s/fr/us/
   localectl list-keymaps |grep "^us"
   us
   us-acentos
   ... 
  • Rappeler des commandes avec leur position dans l'historique
   $ history
   1018  find /usr/share/doc/ -name bonding.txt
   1019  echo this is my last word 
   1020  localectl list-keymaps |grep "^us"
   1021  history
   $ !-3
   echo this is my last word 
   this is my last word
   $ !1018
   find /usr/share/doc/ -name bonding.txt
   /usr/share/doc/kernel-doc-3.10.0/Documentation/networking/bonding.txt