Manipulation de chaîne de caractères Linux

Assigner et afficher une variable

En BASH, une variable est identifiée par l’usage du ‘$’, sauf pour lui attribuer une valeur où l’on omet le ‘$’.

#assignation de la variable
96386@kws:~$ maVariable='Ceci est une chaine de caractères'
    
#utilisation de la variable
96386@kws:~$ echo $mavariable
Ceci est une chaine de caractères

Il est également possible d’utiliser une syntaxe plus explicite qui permet de délimiter clairement quel est le nom de la variable et d’éviter donc plus facilement des erreurs de nommage.

96386@kws:~$ file='homework'
96386@kws:~$ ls /mnt/data/$file_save.doc

Dans cet exemple la variable utilisée est ‘file_save’ et non ‘file’. Le résultat ne sera donc absolument pas celui qu’on attend !

Une façon de délimiter clairement le nom de la variable est d’utiliser les crochets ‘{}’.

    96386@kws:~$ file='homework'
    96386@kws:~$ ls /mnt/data/${file}_save.doc

La variable utilisée ici sera ‘file’ et a pour valeur ‘homework’. Ce qui donne donc la commande suivante une fois la variable substituée.

96386@kws:~$ ls /mnt/data/homework_save.doc

C’est cette syntaxe qui sera utilisée tout au long de cet article.

Modifier la casse

Un des traitements les plus courants est de modifier la casse, que cela soit de passer tout en majuscule, ou en minuscule.

Tout passer en minuscule

Le changement de la casse en minuscule se fait à l’aide de ‘,,’ comme ceci :

96386@kws:~$ test="Hello World !"
96386@kws:~$ echo ${test,,}
hello world !

Tout passer en majuscule

Le changement de la casse en majuscule se fait à l’aide de ‘^^’ comme ceci :

96386@kws:~$ test="Hello World !"
96386@kws:~$ echo ${test^^}
HELLO WORLD !

Ainsi un ‘case’ comme celui-ci

case ${userInput} in
    "oui"|"Oui"|"OUI"|"O"|"o"|"YES"|"Yes"|"yes"|"Y"|y")
        # action si l'utilisateur répond oui
        ;;
    "non"|"Non"|"NON"|"NO|"No"|"no"|"N"|"n")
        # action si l'utilisateur répond non
        ;;
esac

devient simplement :

case ${userInput,,} in
    "oui"|"yes"|"y"|"o")
        # action si l'utilisateur répond oui
    ;;
    "non"|"no"|"n")
        # action si l'utilisateur répond non
    ;;
esac

Récupérer la longueur de la chaine de caractère.

Pour récupérer la longueur d’une chaine de caractère il suffit de précéder le nom de la variable par ‘#’ comme ceci :

${#variable}

96386@kws:~$ VAR="Chaine d'une certaine longueur"
96386@kws:~$ echo ${#VAR}
30

Taille d’un tableau

Il est possible d’obtenir le nombre d’éléments d’un tableau de la façon suivante :

96386@kws:~$ unset VAR
96386@kws:~$ VAR[0]="blablabla"
96386@kws:~$ VAR[1]="azeaze"
96386@kws:~$ VAR[2]="test"
96386@kws:~$ VAR[3]="someText"
96386@kws:~$ VAR[4]=48
96386@kws:~$ VAR[5]=98985
96386@kws:~$ echo ${#VAR[*]}
6
96386@kws:~$ echo ${#VAR[@]}
6

Attention à ne pas oublier les crochets, sinon # retournera simplement la longueur du premier élément du tableau.

96386@kws:~$ unset VAR
96386@kws:~$ VAR[0]="blablabla"
96386@kws:~$ VAR[1]="azeaze"
96386@kws:~$ VAR[2]="test"
96386@kws:~$ echo ${#VAR}
9

Déterminer le nombre de paramètre passés au script

Pour connaitre le nombre de paramètres passés au script ($1, $2 …) on utilisera ‘${#*}’ et ‘${#@}

96386@kws:~$ vi test.sh
#!/bin/bash
echo "\${#*} : '${#*}' \${#@} : '${#@}'"
    
    
96386@kws:~$ bash test.sh var1 test something
${#*} : '3' ${#@} : '3'

Assignation des variables

Plutôt que d’utiliser des ‘if’, ‘else’ et d’assigner des valeurs par défaut si les variables sont vides il existe des mécanismes permettant l’usage ou l’assignation d’une valeur alternative pour ces variables.

Utiliser une alternative

La formulation ${var-alternative} permet l’utilisation d’une alternative si la variable n’est pas assignée

96386@kws:~$ unset VAR # on s'assure que la variable n'existe pas/plus
96386@kws:~$ echo "var: '${VAR-"default"}'"
var: 'default'
96386@kws:~$ VAR=""
96386@kws:~$ echo "var: '${VAR-"default"}'"
var: ''
96386@kws:~$ VAR="VALUE"
96386@kws:~$ echo "var: '${VAR-"default"}'
var: 'VALUE'

96386@kws:~$ VAR2="someVar"
96386@kws:~$ unset VAR
96386@kws:~$ echo ${VAR-$VAR2}
someVar

On constate que si la variable existe mais ne contient aucun caractère, elle n’est pas remplacée par la valeur de substitution. Pour spécifier à Bash que les variables vides sont également à remplacer nous allons utiliser la forme suivante : ${var:-alternative} (ajout du ‘:’).

96386@kws:~$ unset VAR # on s'assure que la variable n'existe pas/plus
96386@kws:~$ echo "'${VAR:-"default"}'"
'default'
96386@kws:~$ VAR=""
96386@kws:~$ echo "'${VAR:-"default"}'
'default'
96386@kws:~$ VAR="VALUE"
96386@kws:~$ echo "'${VAR:-"default"}'"
'VALUE' 
96386@kws:~$ VAR2="someVar"
96386@kws:~$ VAR=""
96386@kws:~$ echo ${VAR:-$VAR2}
someVar

Assigner une valeur par défaut

La méthode précédente permettait de retourner une valeur différente lors de l’usage de la variable mais la valeur de la variable restait inchangée. La syntaxe ${var= »alternativeValue »} permet de d’assigner une valeur à la variable si celle ci n’est pas déclarée .

96386@kws:~$ unset VAR # on s'assure que la variable n'existe pas/plus
96386@kws:~$ echo "var :'$VAR'"
var :''
96386@kws:~$ echo "var :'${VAR=default}'"
var :'default'
96386@kws:~$ echo "var :'$VAR'"
var :'default'

Comme pour l’utilisation d’une valeur de substitution, il est possible de différencier une variable non assignée d’une variable vide. ${VAR:=default} permet de remplacer la valeur des variables déclarée mais vides.

96386@kws:~$ VAR=""
96386@kws:~$ echo "var :'$VAR'"
var :''
96386@kws:~$ echo "var :'${VAR=default}'"
var :''
96386@kws:~$ echo "var :'$VAR'"
var :''
96386@kws:~$ echo "var :'${VAR:=default}'"
var :'default'
96386@kws:~$ echo "var :'$VAR'"
var :'default'

Utiliser une alternative et quitter

Toujours dans la liste des valeurs alternatives, il est possible d’utiliser une valeur par défaut et de quitter le programme avec un code de de retour ‘1’. La formulation est la suivante : ${var?alternative]

96386@kws:~$ unset var
96386@kws:~$ parametre=${VAR?"Var is not set"}
bash: VAR: Var is not set

La formulation reste la même pour spécifier que l’on souhaite aussi filtrer les variables définies mais vides : ${var:? »Var is not set or empty »}

96386@kws:~$ var=""
96386@kws:~$ parametre=${VAR:?"Var is not set or empty"}
-bash: var: Var is not set or empty

Extraire une sous-chaine

Il est courant de travailler sur des fractions d’une chaine de caractères. Il est possible d’obtenir ses éléments avec la fonction suivante : ${var:<position>:<longueur>}

96386@kws:~$ VAR="Hello world !"
96386@kws:~$ echo "'${VAR:6}'"
'world !'
96386@kws:~$ echo "'${VAR:1:4}'"
'ello'
96386@kws:~$ echo "'${VAR:6:20}'"
'world !'
96386@kws:~$ echo "'${VAR::3}'"
'first 3'
96386@kws:~$ echo "'${VAR: -3}'"
'd !'
96386@kws:~$ echo "'${VAR::-1}'"
'Hello world '

Supprimer une sous-chaine

Il est possible de se débarrasser rapidement de chaine de caractères précédant ou suivant la partie recherchée, pour récupérer le nom d’un fichier sans les répertoires auquel il appartient ou sans son extension par exemple !

‘#’ Supprimer depuis le début de la chaine

L’utilisation du ‘#’ (${var#pattern}) permet de supprimer la première portion correspondant au pattern que l’on passe en paramètre.

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR#h*o}'"
' world !'.

##

Le double ‘#’ (${var##pattern) s’utilise de la même façon que le simple ‘#’ à la différence que celui-ci supprimera la chaine correspondante la plus longue.

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR##h*o}'"
'rld !'

‘%’ Supprimer depuis la fin de la chaine

Le ‘%’ (${var%pattern}) permet de supprimer la chaine correspondante à notre pattern depuis la fin de notre variable

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR%o*}'"
'hello w'

%%

Comme pour le ‘##’ le double %% permet de sélectionner la plus grande chaine, ici depuis la fin de la variable.

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR%%o*}'"
'hell'

A noter que ces outils ne permettent la suppression de chaine de caractères que depuis l’un des bords de la variable.

Pour supprimer une sous-chaine présente au milieu de la variable on pourra utiliser de remplacement de chaine de caractère ‘/’ sans lui passer de chaine de remplacement. Pour supprimer la première occurence :

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR/o/}'"
'hell world !'
96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR/l*o/}'"
'herld !'

Pour supprimer l’ensemble des occurrences on utilisera ‘//’

96386@kws:~$ VAR="hello world !"
96386@kws:~$ echo "'${VAR//o/}'"
'hell wrld !'

Exemple d’utilisation

Les traitements de chaines de caractère que nous voulons voir sont très pratiques lorsque, par exemple, de la manipulation de fichiers. Prenons ici comme exemple le fichier ‘/etc/apache2/sites-available/000-default.conf’ et regardons ensemble comment extraire le path, le nom du fichier et son extension.

96386@kws:~$ file='/etc/apache2/sites-available/000-default.conf'

Pour récupérer le path, nous allons simplement tout supprimer depuis la fin du fichier jusqu’au premier ‘/’ rencontré

96386@kws:~$ file='/etc/apache2/sites-available/000-default.conf'
96386@kws:~$ filePath=${file%/*}
96386@kws:~$ echo $filePath 
/etc/apache2/sites-available

Pour récupérer le fichier, nous allons procéder de la façon inverse : nous allons tout supprimer depuis le début jusqu’au dernier ‘/’

96386@kws:~$ file='/etc/apache2/sites-available/000-default.conf'
96386@kws:~$ fileName=${file##*/}
96386@kws:~$ echo $fileName 
000-default.conf

Pour supprimer l’extension de notre fichier nous allons supprimer tout les caractères depuis la fin jusqu’au premier ‘.’

96386@kws:~$ file='/etc/apache2/sites-available/000-default.conf'
96386@kws:~$ fileNameShort=${fileName%.*}
96386@kws:~$ echo $fileNameShort 
000-default

Et enfin pour extraire l’extension nous allons garder uniquement ce qu’il reste après le dernier ‘.’

96386@kws:~$ file='/etc/apache2/sites-available/000-default.conf'
96386@kws:~$ fileExtension=${fileName##*.}
96386@kws:~$ echo $fileExtension 
conf

Remplacement de sous-chaine

En plus des possibilités de suppression et d’extraction de sous-chaine de caractère, il est également possible de remplacer certaines expressions dans notre variable avec l’utilisation du ‘/’.

Remplacer le premier élément trouvé.

Pour remplacer le première élément correspondant, on utilisera la syntaxe suivante :${var/pattern/remplacement/}.

96386@kws:~$ VAR="blablabla"
96386@kws:~$ echo "'${VAR/a/o}'"
'bloblabla'
96386@kws:~$ echo "'${VAR/bl/pl}'"
'pliblablobleblu'
96386@kws:~$ echo "'${VAR/bla/123}'"
'bli123blobleblu'

Remplacer l’ensemble des éléments correspondants.

Pour remplacer l’ensemble des éléments correspondants par la chaine passé en deuxième paramètre nous utiliserons le double ‘/’.

${string//substring/replacement}

96386@kws:~$ VAR="blablabla"
96386@kws:~$ echo "'${VAR//a/o}'"
'blobloblo'
96386@kws:~$ VAR="bliblablobleblu"
96386@kws:~$ echo "'${VAR//bl/pl}'"
'pliplaplopleplu'

Remplacer le dernier élément correspondant.

Pour remplacer la plus grande correspondance depuis le début de la chaine on utilisera le ‘/#’

${string/#substring/replacement}

96386@kws:~$ var="Hello, world !"
96386@kws:~$ echo "'${var/#*o/i}'"
'irld !'

Ce qui est similaire à ‘/’

96386@kws:~$ echo "'${VAR/*o/i}'"
'irld !'

Pour remplacer la plus longue correspondance depuis la fin de la chaine de caractère, on utilisera le ‘/%’

${string/%substring/replacement}

96386@kws:~$ var="Hello, world !"
96386@kws:~$ echo "'${var/%o/i}'"
'Hello, world !'
96386@kws:~$ echo "'${var/%o*/il}'"
'Helli'

Ce qui est similaire à ‘/’

96386@kws:~$ echo "'${VAR/o*/i}'"
'irld !'

setgid setuid vtom erreur stickybit

Warning: Problem at the time of the initialization of the secondary groups.: Operation not permitted
Warning: Error setgid(54321), Operation not permitted.: Operation not permitted
Warning: Error setuid(54321), Operation not permitted.: Operation not permitted

——————-

cd /opt/vtom/abm/bin/

ll bdaemon
-rwxr-xr-x 1 vtom vtom 3208520 Mar 13 09:46 bdaemon

chown root:root bdaemon
chmod 4755 bdaemon

-rwsr-xr-x 1 root root 3208520 Mar 13 09:46 bdaemon

 

 

espace dans les noms de fichiers

Remplacer les espaces par des _ dans les noms de fichier d’un dossier.

Sous Windows

cd mon_dossier
for /f "delims=" %%a in ('dir /b') do call :cmd "%%a"
exit
:cmd
set fichierbck=%~1
set fichier=%fichierbck: =_%
ren "%fichierbck%" "%fichier%"

Sous Linux

rename 's/[[:blank:]]/_/g' *

Remplacement temporaire

#IFS = field separator, so only accept end of line and not space as filename may contain space
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for v_fic in `find ${w_rep_purge}/ -type f -mtime ${w_jour_purge} -name "*.${w_extension}" | grep ${w_grep}`
 do
    echo " - Suppression du fichier [${v_fic}] ..."
#    rm -f ${v_fic}
    ls -la ${v_fic}
 done
#IFS = restore old filed separator to not changed stand shell comportement
IFS=$SAVEIFS

test dossier ou fichier exist

backup=/backups/${sid_oracle}/cold/

if [ ! -d ${backup} ]; then
mkdir ${backup}
else
rm -f ${backup}*
fi

FILE=/etc/resolv.conf
if test -f "$FILE"; then
    echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [[ -f "$FILE" ]]; then
    echo "$FILE exist"
fi
FILE=/etc/resolv.conf
if [ -f "$FILE" ]; then
    echo "$FILE exist"
else 
    echo "$FILE does not exist"
fi

Remote command

Linux :

 Serveur :

plink -ssh -l root -pw mot_de_passe nom_du_serveur « commande »

Windows :

 Services :

sc \\nom_du_serveur query nom_du_service  » | find « RUNNING »
if !errorlevel! equ 0  sc \\nom_du_serveur stop « nom_du_service »

sc \\nom_du_serveur query nom_du_service

sc \\nom_du_serveur start nom_du_service

sc \\nom_du_serveur stop nom_du_service

 Serveur :

shutdown /s /m \\nom_du_serveur /t 30 /c « BatchStop » /f /d p:4:1

QUSER /SERVER:nom_du_serveur

LOGOFF username /SERVER:nom_du_serveur /V 

 Psexec :

set PATH=%PATH%;c:\Program Files\pstools

L:\Soft\PsExec\psexec.exe \\nom_du_serveur cmd /c commande

psexec \\nom_du_serveur cmd /c change logon /query

psexec \\nom_du_serveur cmd /c change logon /enable

psexec \\nom_du_serveur cmd /c change logon /disable

Manipuler les chaînes de caractères

http://abs.traduc.org/abs-5.3-fr/ch09s02.html

 

Bash supporte un nombre surprenant d’opérations de manipulation de chaînes de caractères. Malheureusement, ces outils manquent d’unité. Certains sont un sous-ensemble de la substitution de paramètre et les autres font partie des fonctionnalités de la commande UNIX expr. Ceci produit une syntaxe de commande non unifiée et des fonctionnalités qui se recoupent, sans parler de la confusion engendrée.

Longueur de chaînes de caractères

${#chaine}
expr length $chaine
C’est l’équivalent de la fonction strlen() en C.
expr « $chaine » : ‘.*’
chaineZ=abcABC123ABCabc

echo ${#chaineZ}                 # 15
echo `expr length $chaineZ`      # 15
echo `expr "$chaineZ" : '.*'`    # 15

Exemple 9.10. Insérer une ligne blanche entre les paragraphes d’un fichier texte

#!/bin/bash
# paragraph-space.sh

# Insère une ligne blanche entre les paragraphes d'un fichier texte.
# Usage: $0 <NOMFICHIER

LONGUEUR_MINI=45        # Il peut être nécessaire de changer cette valeur.
#  Suppose que les lignes plus petites que $LONGUEUR_MINI caractères
#+ terminent un paragraphe.

while read ligne  # Pour toutes les lignes du fichier...
do
  echo "$ligne"   # Afficher la ligne.

  longueur=${#ligne}
  if [ "$longueur" -lt "$LONGUEUR_MINI" ]
    then echo    # Ajoute une ligne blanche après chaque petite ligne.
  fi  
done

exit 0

 

Longueur de sous-chaînes correspondant à un motif au début d’une chaîne

expr match « $chaine » ‘$souschaine’
$souschaine est une expression rationnelle.
expr « $chaine » : ‘$souschaine’
$souschaine est une expression rationnelle.

chaineZ=abcABC123ABCabc
#       |------|

echo `expr match "$chaineZ" 'abc[A-Z]*.2'`   # 8
echo `expr "$chaineZ" : 'abc[A-Z]*.2'`       # 8

Index

expr index $chaine $souschaine
Position numérique dans $chaine du premier caractère dans $souschaine qui correspond.

chaineZ=abcABC123ABCabc
echo `expr index "$chaineZ" C12`             # 6
                                             # C position.

echo `expr index "$chaineZ" 1c`              # 3
# 'c' (à la position #3) correspond avant '1'.

Ceci est l’équivalent le plus proche de strchr() en C.

Extraction d’une sous-chaîne

${chaine:position}
Extrait une sous-chaîne de $chaine à partir de la position $position.

Si le paramètre $chaine est « * » ou « @ », alors cela extrait les paramètres de position[36] commençant à $position.

${chaine:position:longueur}
Extrait $longueur caractères d’une sous-chaîne de $chaine à la position $position.

chaineZ=abcABC123ABCabc
#       0123456789.....
#       indexage base 0.

echo ${chaineZ:0}                            # abcABC123ABCabc
echo ${chaineZ:1}                            # bcABC123ABCabc
echo ${chaineZ:7}                            # 23ABCabc

echo ${chaineZ:7:3}                          # 23A
                                             # Trois caractères de la sous-chaîne.

# Est-il possible d'indexer à partir de la fin de la chaîne ?

echo ${chaineZ:-4}                           # abcABC123ABCabc
# Par défaut la chaîne complète, comme dans ${parametre:-default}.
# Néanmoins...

echo ${chaineZ:(-4)}                         # Cabc
echo ${chaineZ: -4}                          # Cabc
# Maintenant, cela fonctionne.
#  Des parenthèses ou des espaces ajoutés permettent un échappement du paramètre
#+ de position.

# Merci, Dan Jacobson, pour cette indication.

Les arguments position et longueur peuvent devenir des « paramètres », c’est-à-dire représentés par une variable, plutôt que par une constante numérique.

Exemple 9.11. Générer « aléatoirement » une chaîne de huit caractères

#!/bin/bash
# rand-string.sh
# Générer aléatoirement une chaîne de huit caractères.

if [ "-n $1" ]  #  Si présence d'un argument en ligne de commande,
then            #+ alors l'utiliser comme chaîne de départ.
  chaine0="$1"
else            #  Sinon, utiliser le PID du script.
  chaine0="$$"
fi

POS=2  # On commence en position 2.
LONG=8  # Extraction de huit caractères.

chaine1=$( echo "$chaine0" | md5sum | md5sum )
# Double mixage :            ^^^^^^   ^^^^^^

chainealeatoire="${chaine1:$POS:$LONG}"
# Peut se paramétrer       ^^^^ ^^^^^

echo "$chainealeatoire"

exit $?

# bozo$ ./rand-string.sh mon-motdepasse
# 1bdd88c4

#  Non, ceci n'est pas recommandé
#+ comme méthode sûre de génération de mots de passe.

 

Si le paramètre $chaine est « * » ou « @ », alors ceci extrait un maximum de $longueur du paramètre de position, en commençant à $position.

echo ${*:2}          # Affiche le deuxième paramètre de position et les suivants.
echo ${@:2}          # Identique à ci-dessus.

echo ${*:2:3}        # Affiche trois paramètres de position, en commençant par le deuxième.
expr substr $chaine $position $longueur
Extrait $longueur caractères à partir de $chaine en commençant à $position.

chaineZ=abcABC123ABCabc
#       123456789......
#       indexage base 1.

echo `expr substr $chaineZ 1 2`              # ab
echo `expr substr $chaineZ 4 3`              # ABC

expr match « $chaine » ‘\($souschaine\)’
Extrait $souschaine à partir du début de $chaine, et où $souschaine est une expression rationnelle.
expr « $chaine » : ‘\($souschaine\)’
Extrait $souschaine à partir du début de $chaine, et où $souschaine est une expression rationnelle.

chaineZ=abcABC123ABCabc
#       =======

echo `expr match "$chaineZ" '\(.[b-c]*[A-Z]..[0-9]\)'`   # abcABC1
echo `expr "$chaineZ" : '\(.[b-c]*[A-Z]..[0-9]\)'`       # abcABC1
echo `expr "$chaineZ" : '\(.......\)'`                   # abcABC1
# Toutes les formes ci-dessus donnent un résultat identique.
expr match « $chaine » ‘.*\($souschaine\)’
Extrait $souschaine à la fin de $chaine, et où $souschaine est une expression rationnelle.
expr « $chaine » : ‘.*\($souschaine\)’
Extrait $souschaine à la fin de $chaine, et où $souschaine est une expression rationnelle.

chaineZ=abcABC123ABCabc
#                ======

echo `expr match "$chaineZ" '.*\([A-C][A-C][A-C][a-c]*\)'`    # ABCabc
echo `expr "$chaineZ" : '.*\(......\)'`                       # ABCabc

Suppression de sous-chaînes

${chaine#souschaine}
Supprime la correspondance la plus petite de $souschaine à partir du début de $chaine.
${chaine##souschaine}
Supprime la correspondance la plus grande de $souschaine à partir du début de $chaine.

chaineZ=abcABC123ABCabc
#       |----|
#       |----------|

echo ${chaineZ#a*C}      # 123ABCabc
# Supprime la plus petite correspondance entre 'a' et 'C'.

echo ${chaineZ##a*C}     # abc
# Supprime la plus grande correspondance entre 'a' et 'C'.
${chaine%souschaine}
Supprime la plus petite correspondance de $souschaine à partir de la fin de $chaine.

Par exemple :

# Renomme tous les fichiers de $PWD
#+ en remplaçant le suffixe "TXT" par "txt".
# Par exemple, "fichier1.TXT" devient "fichier1.txt" . . .

SUFF=TXT
suff=txt

for i in $(ls *.$SUFF)
do
  mv -f $i ${i%.$SUFF}.$suff
  #  Ne modifie rien *en dehors* de la correspondance la plus courte
  #+ commençant du côté droit de $i . . .
done ### Ceci pourrait être condenser en une ligne si nécessaire.

# Thank you, Rory Winston.
${chaine%%souschaine}
Supprime la plus grande correspondance de $souschaine à partir de la fin de $chaine.

chaineZ=abcABC123ABCabc
#                    ||
#        |------------|

echo ${chaineZ%b*c}      # abcABC123ABCa
#  Supprime la plus petite correspondance entre 'b' et 'c', à partir de la fin
#+ de $chaineZ.

echo ${chaineZ%%b*c}     # a
#  Supprime la plus petite correspondance entre 'b' et 'c', à partir de la fin
#+ de $chaineZ.

Cet opérateur est utilisé pour générer des noms de fichier.

Exemple 9.12. Convertir des formats de fichiers graphiques avec une modification du nom du fichier

#!/bin/bash
#  cvt.sh:
#  Convertit les fichiers image MacPaint contenus dans un répertoire dans le
#+ format "pbm".

#  Utilise le binaire "macptopbm" provenant du paquetage "netpbm",
#+ qui est maintenu par Brian Henderson (bryanh@giraffe-data.com).
#  Netpbm est un standard sur la plupart des distributions Linux.

OPERATION=macptopbm
SUFFIXE=pbm         # Suffixe pour les nouveaux noms de fichiers.

if [ -n "$1" ]
then
  repertoire=$1      # Si le nom du répertoire donné en argument au script...
else
  repertoire=$PWD    # Sinon, utilise le répertoire courant.
fi  

#  Suppose que tous les fichiers du répertoire cible sont des fichiers image
# + MacPaint avec un suffixe de nom de fichier ".mac".

for fichier in $repertoire/*  # Filename globbing.
do
  nomfichier=${fichier%.*c} #  Supprime le suffixe ".mac" du nom du fichier
                            #+ ('.*c' correspond à tout ce qui se trouve
                            #+ entre '.' et 'c', inclus).
  $OPERATION $fichier > $nomfichier.$SUFFIXE
    # Redirige la conversion vers le nouveau nom du fichier.
    rm -f $fichier          # Supprime le fichier original après sa convertion.
  echo "$nomfichier.$SUFFIXE"  # Trace ce qui se passe sur stdout.
done

exit 0

# Exercice
# --------
#  À ce stade, ce script convertit *tous* les fichiers du répertoire courant.
#  Modifiez le pour qu'il renomme *seulement* les fichiers dont l'extension est
#+ ".mac".

Exemple 9.13. Convertir des fichiers audio en ogg

#!/bin/bash
# ra2ogg.sh : Convertit des fichiers audio de streaming (*.ra) en ogg.

# Utilise le programme "mplayer" :
#      http://www.mplayerhq.hu/homepage
#      Vous aurez peut-être besoin d'installer les codecs appropriés
#+     pour que ce script fonctionne.
# Utilise la bibliothèque "ogg" et "oggenc" :
#      http://www.xiph.org/

PREFIXE_FICHIER_RESULTAT=${1%%ra}      # Supprime le suffixe "ra".
SUFFIXE_FICHIER_RESULTAT=wav           # Suffixe pour le fichier wav.
FICHIER_RESULTAT="$PREFIXE_FICHIER_RESULTAT""$SUFFIXE_FICHIER_RESULTAT"
E_SANSARGS=65

if [ -z "$1" ]          # Un nom de fichier à convertir doit être spécifié.
then
  echo "Usage: `basename $0` [nom_fichier]"
  exit $E_SANSARGS
fi

##########################################################################
mplayer "$1" -ao pcm:file=$FICHIER_RESULTAT
oggenc "$FICHIER_RESULTAT"  # Corrige l'extension du fichier ajoutée automatiquement pas oggenc.
##########################################################################

rm "$FICHIER_RESULTAT"      # Supprime le fichier temporaire *.wav.
                   # Si vous voulez le conserver, commentez la ligne ci-dessus.

exit $?

#  Note :
#  -----
#  Sur un site web, cliquer seulement sur un fichier audio *.ram
#+ récupère l'URL du fichier audio, le fichier *.ra.
#  Vous pouvez ensuite utiliser "wget" ou un autre outil similaire
#+ pour télécharger vous-même le fichier *.ra.

#  Exercices :
#  ----------
#  Actuellement, ce script convertit seulement les noms de fichier *.ra.
#  Ajoutez de la flexibilité en autorisant l'utilisation de *.ram et d'autres noms de fichier.
#
#  Si vous êtes réellement ambitieux, étendez le script pour réaliser automatiquement
#+ les téléchargements et les convertions des fichiers audio.
#  À partir d'une URL, récupérez les fichiers audio (en utilisant "wget")
#+ et convertissez-les.

Une simple émulation de getopt en utilisant des constructions d’extraction de sous-chaînes.

Exemple 9.14. Émuler getopt

#!/bin/bash
# getopt-simple.sh
# Auteur : Chris Morgan
# Utilisé dans le guide ABS avec sa permission.

getopt_simple()
{
    echo "getopt_simple()"
    echo "Les paramètres sont '$*'"
    until [ -z "$1" ]
    do
      echo "Traitement du paramètre : '$1'"
      if [ ${1:0:1} = '/' ]
      then
          tmp=${1:1}               # Supprime le '/' devant...
          parametre=${tmp%%=*}     # Extrait le nom.
          valeur=${tmp##*=}        # Extrait la valeur.
          echo "Paramètre : '$parametre', valeur: '$valeur'"
          eval $parametre=$valeur
      fi
      shift
    done
}

# Passe toutes les options à getopt_simple().
getopt_simple $*

echo "test vaut '$test'"
echo "test2 vaut '$test2'"

exit 0

---

sh getopt_example.sh /test=valeur1 /test2=valeur2

Les paramètres sont '/test=valeur1 /test2=valeur2'
Traitement du paramètre : '/test=valeur1'
Paramètre : 'test', valeur: 'valeur1'
Traitement du paramètre : '/test2=valeur2'
Paramètre : 'test2', valeur : 'valeur2'
test vaut 'valeur1'
test2 vaut 'valeur2'

Remplacement de sous-chaîne

${chaine/souschaine/remplacement}
Remplace la première correspondance de $souschaine par $remplacement.
${chaine//souschaine/remplacement}
Remplace toutes les correspondances de $souschaine avec $remplacement.

chaineZ=abcABC123ABCabc

echo ${chaineZ/abc/xyz}           # xyzABC123ABCabc
                                  #  Remplace la première correspondance de
                                  #+ 'abc' avec 'xyz'.

echo ${chaineZ//abc/xyz}          # xyzABC123ABCxyz
                                  #  Remplace toutes les correspondances de
                                  #+ 'abc' avec 'xyz'.
${chaine/#souschaine/remplacement}
Si $souschaine correspond au début de $chaine, substitue $remplacement à $souschaine.
${chaine/%souchaine/remplacement}
Si $souschaine correspond à la fin de $chaine, substitue $remplacement à $souschaine.

chaineZ=abcABC123ABCabc

echo ${chaineZ/#abc/XYZ}          # XYZABC123ABCabc
                                  #  Remplace la correspondance de fin de
                                  #+ 'abc' avec 'XYZ'.

echo ${chaineZ/%abc/XYZ}          # abcABC123ABCXYZ
                                  #  Remplace la correspondance de fin de
                                  #+ 'abc' avec 'XYZ'.

9.2.1. Manipuler des chaînes de caractères avec awk

Un script Bash peut utiliser des fonctionnalités de manipulation de chaînes de caractères de awk comme alternative à ses propres fonctions intégrées.

Exemple 9.15. Autres moyens d’extraire des sous-chaînes

#!/bin/bash
# substring-extraction.sh

Chaine=23skidoo1
#      012345678    Bash
#      123456789    awk
# Notez les différents systèmes d'indexation de chaînes :
# Bash compte le premier caractère d'une chaîne avec '0'.
# Awk  compte le premier caractère d'une chaîne avec '1'.

echo ${Chaine:2:4} # position 3 (0-1-2), longueur de quatre caractères
                                         # skid

# L'équivalent awk de ${string:position:longueur} est substr(string,position,longueur).
echo | awk '
{ print substr("'"${Chaine}"'",3,4)      # skid
}
'
#  Envoyé un "echo" vide à awk donne une entrée inutile, et donc permet d'éviter
#+ d'apporter un nom de fichier.

exit 0

fichier + horodatage + zip

#!/bin/bash
ps -ef|grep tomcat |grep -v grep
sh /etc/init.d/tomcat6 stop
ps -ef|grep tomcat |grep -v grep

fic_log=$1
echo fic_log : ${fic_log}

w_date=$(date +%Y%m%d_%H%M%S)

mv ${fic_log} ${fic_log}.${w_date}.log

gzip ${fic_log}.${w_date}.log

ls -latr ${fic_log}*

Pour zipper :

Pour chaque fichier talend-log-central.log.2016-06* un fichier talend-log-central.log.2016-06*.gz sera créé.

gzip talend-log-central.log.2016-06.gz talend-log-central.log.2016-06*

exemple :

root@vlbid16x:/soft/Talend-6.1.1/logserv/elasticsearch-1.5.2/logs# ll -h talend-log-central.log.2016-06*
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 2 23:59 talend-log-central.log.2016-06-01
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 3 23:59 talend-log-central.log.2016-06-02
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 4 23:59 talend-log-central.log.2016-06-03
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 5 23:59 talend-log-central.log.2016-06-04
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 6 23:59 talend-log-central.log.2016-06-05
-rw-rw-r-- 1 talenduser talenduser 1.4M Jun 7 23:59 talend-log-central.log.2016-06-06
-rw-rw-r-- 1 talenduser talenduser 1.4M Jun 8 23:59 talend-log-central.log.2016-06-07
-rw-rw-r-- 1 talenduser talenduser 1.4M Jun 9 23:59 talend-log-central.log.2016-06-08
-rw-rw-r-- 1 talenduser talenduser 1.4M Jun 10 23:59 talend-log-central.log.2016-06-09
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 11 23:59 talend-log-central.log.2016-06-10
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 12 23:59 talend-log-central.log.2016-06-11
-rw-rw-r-- 1 talenduser talenduser 871K Jun 13 13:53 talend-log-central.log.2016-06-12
-rw-rw-r-- 1 talenduser talenduser 726K Jun 14 23:59 talend-log-central.log.2016-06-13
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 15 23:59 talend-log-central.log.2016-06-14
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 16 23:59 talend-log-central.log.2016-06-15
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 17 23:59 talend-log-central.log.2016-06-16
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 18 23:59 talend-log-central.log.2016-06-17
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 19 23:59 talend-log-central.log.2016-06-18
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 20 23:59 talend-log-central.log.2016-06-19
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 21 23:59 talend-log-central.log.2016-06-20
-rw-rw-r-- 1 talenduser talenduser 1.3M Jun 22 23:59 talend-log-central.log.2016-06-21
-rw-rw-r-- 1 talenduser talenduser 1.2M Jun 23 23:59 talend-log-central.log.2016-06-22
-rw-rw-r-- 1 talenduser talenduser 663K Jun 24 12:17 talend-log-central.log.2016-06-23
-rw-rw-r-- 1 talenduser talenduser 4.6G Jun 25 23:59 talend-log-central.log.2016-06-24
-rw-rw-r-- 1 talenduser talenduser 5.4G Jun 25 23:59 talend-log-central.log.2016-06-25
-rw-rw-r-- 1 talenduser talenduser 2.7G Jun 27 23:59 talend-log-central.log.2016-06-26
-rw-rw-r-- 1 talenduser talenduser 865M Jun 28 23:59 talend-log-central.log.2016-06-27
-rw-rw-r-- 1 talenduser talenduser 2.2G Jun 29 23:59 talend-log-central.log.2016-06-28
-rw-rw-r-- 1 talenduser talenduser 519M Jun 30 23:59 talend-log-central.log.2016-06-29
-rw-rw-r-- 1 talenduser talenduser 2.1G Jul 1 23:59 talend-log-central.log.2016-06-30

devient

root@vlbid16x:/soft/Talend-6.1.1/logserv/elasticsearch-1.5.2/logs# ll -h talend-log-central.log.2016-06*
-rw-rw-r-- 1 talenduser talenduser 48K Jun 2 23:59 talend-log-central.log.2016-06-01.gz
-rw-rw-r-- 1 talenduser talenduser 48K Jun 3 23:59 talend-log-central.log.2016-06-02.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 4 23:59 talend-log-central.log.2016-06-03.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 5 23:59 talend-log-central.log.2016-06-04.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 6 23:59 talend-log-central.log.2016-06-05.gz
-rw-rw-r-- 1 talenduser talenduser 28K Jun 7 23:59 talend-log-central.log.2016-06-06.gz
-rw-rw-r-- 1 talenduser talenduser 29K Jun 8 23:59 talend-log-central.log.2016-06-07.gz
-rw-rw-r-- 1 talenduser talenduser 28K Jun 9 23:59 talend-log-central.log.2016-06-08.gz
-rw-rw-r-- 1 talenduser talenduser 29K Jun 10 23:59 talend-log-central.log.2016-06-09.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 11 23:59 talend-log-central.log.2016-06-10.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 12 23:59 talend-log-central.log.2016-06-11.gz
-rw-rw-r-- 1 talenduser talenduser 19K Jun 13 13:53 talend-log-central.log.2016-06-12.gz
-rw-rw-r-- 1 talenduser talenduser 28K Jun 14 23:59 talend-log-central.log.2016-06-13.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 15 23:59 talend-log-central.log.2016-06-14.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 16 23:59 talend-log-central.log.2016-06-15.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 17 23:59 talend-log-central.log.2016-06-16.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 18 23:59 talend-log-central.log.2016-06-17.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 19 23:59 talend-log-central.log.2016-06-18.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 20 23:59 talend-log-central.log.2016-06-19.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 21 23:59 talend-log-central.log.2016-06-20.gz
-rw-rw-r-- 1 talenduser talenduser 47K Jun 22 23:59 talend-log-central.log.2016-06-21.gz
-rw-rw-r-- 1 talenduser talenduser 46K Jun 23 23:59 talend-log-central.log.2016-06-22.gz
-rw-rw-r-- 1 talenduser talenduser 26K Jun 24 12:17 talend-log-central.log.2016-06-23.gz
-rw-rw-r-- 1 talenduser talenduser 106M Jun 25 23:59 talend-log-central.log.2016-06-25.gz
-rw-rw-r-- 1 talenduser talenduser 48M Jun 27 23:59 talend-log-central.log.2016-06-26.gz
-rw-rw-r-- 1 talenduser talenduser 24M Jun 28 23:59 talend-log-central.log.2016-06-27.gz
-rw-rw-r-- 1 talenduser talenduser 39M Jun 29 23:59 talend-log-central.log.2016-06-28.gz
-rw-rw-r-- 1 talenduser talenduser 14M Jun 30 23:59 talend-log-central.log.2016-06-29.gz
-rw-rw-r-- 1 talenduser talenduser 35M Jul 1 23:59 talend-log-central.log.2016-06-30.gz

Pour dézipper :

gunzip talend-log-central.log.2016-06-30.gz

Chaine de boot Linux

Sur Redhat 7.1 (Fonctionne sur Vldtb01p)

Les  scripts lancés au démarrage sont dans le fichier /etc/rc.local Ce fichier doit être exécutable

ll /etc/rc.local
chmod +x /etc/rc.local
lrwxrwxrwx. 1 root root 13 Sep 22 16:11 /etc/rc.local -> rc.d/rc.local

Exemple :

[root@vldtb02x ~]# cat /etc/rc.local
 #!/bin/bash
 # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES
 #
 # It is highly advisable to create own systemd services or udev rules
 # to run scripts during boot instead of using this file.
 #
 # In contrast to previous versions due to parallel execution during boot
 # this script will NOT be run after all other services.
 #
 # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure
 # that this script will be executed during boot.
# touch /var/lock/subsys/local
echo Start Vtom Agent
 . /etc/init.d/boot_start_vtom.sh
echo Start Oracle
 . /etc/init.d/start_oracle.sh
echo Zabbix Agent
. /etc/init.d/zabbix_agent_start.sh
 echo su -l ora112 -c /exploit/scripts/start_oracle.sh> /etc/init.d/start_oracle.sh

chmod +x /etc/init.d/start_oracle.sh

Fichier_non_vide

Sous Linux

#!/bin/bash
cd /exploit/logs
find *.e -type f -not -empty

Sous Windows

rem ——————————————– rem ce script rechercher les fichiers non vide rem pour un type (extension) donné rem dans une directorie donné rem ——————————————–

@Echo Off

echo extension : %1 echo dossier : %2

setlocal ENABLEDELAYEDEXPANSION

set /A P1=0 set fic=%1 set dossier=%2

for /R %dossier% %%i in (%fic%) do if « %%~zi » geq « 1 » ( echo %%~nxzi set /A P1=!P1!+1 )

echo Il y a !P1! fichiers non vide

set /A nb_fic=!P1!

if %nb_fic% equ 0 goto TERMINE goto ERREUR

:ERREUR Echo « il y a !P1! Pb sur ces serveurs » rem cd %ABM_LOGS% rem copy /Y %TOM_LOG_PATH_E% log_erreur.txt rem copy /Y %TOM_LOG_PATH_O% log_standard.txt rem %ABM_BIN%/tmail -c %ABM_BIN%/tmail.ini -to eric.fougere@faiveleytransport.com -sub « DCB – VTOM : ERREUR job : %TOM_JOB% » -msg « fichier log non vide MACHINE : %TOM_HOST% %TOM_JOB% : Les log errors ne sont pas vides. » -att log_standard.txt;log_erreur.txt

:TERMINE exit /b %nb_fic%

my_coldbackup_database.sh

w_date=$(date '+%Y_%m_%d_%H_%M_%S')
# avec generation log
# su mysql --command="mysqlbackup --user=root --password=motdepasse --ibbackup=/opt/mysql/meb-3.5/bin/ibbackup /etc/mysql/my.cnf /data/backups/mysql" > /exploit/logs/my-backup-${w_date}.log
# sans log pour remonter dans VTOM
su mysql --command="mysqlbackup --user=root --password=motdepasse --ibbackup=/opt/mysql/meb-3.5/bin/ibbackup /etc/mysql/my.cnf /data/backups/mysql"
[root@pdtb2 scripts]# cat my_coldbackup_database.sh
#w_date=$(date '+%Y_%m_%d_%H_%M_%S')
w_date=$(date '+%A')
BACKUPDIR=/data/backups/mysql/${w_date}_coldbackup
DATADIR=/data/mysql
echo "rm -rf $BACKUPDIR"
rm -rf $BACKUPDIR
echo "stop mysql database"
/exploit/scripts/my_stop_database.sh
su mysql --command="mkdir $BACKUPDIR"
echo "copy my.cnf"
cp -p /etc/mysql/my.cnf $BACKUPDIR/
echo "copy database sans compression"
time cp -rp $DATADIR/ $BACKUPDIR/
echo "start mysql database"
/exploit/scripts/my_start_database.sh
sleep 120

my_backup_database.sh

w_date=$(date '+%Y_%m_%d_%H_%M_%S')
# avec generation log
# su mysql --command="mysqlbackup --user=root --password=motdepasse --ibbackup=/opt/mysql/meb-3.5/bin/ibbackup /etc/mysql/my.cnf /data/backups/mysql" > /exploit/logs/my-backup-${w_date}.log
# sans log pour remonter dans VTOM
su mysql --command="mysqlbackup --user=root --password=motdepasse --ibbackup=/opt/mysql/meb-3.5/bin/ibbackup /etc/mysql/my.cnf /data/backups/mysql"

my_alertlog.sh

#!/bin/sh
echo "----------------------------------------------"
echo " Recherche des erreurs dans les log"
echo "----------------------------------------------"
echo " "
fic=$1 # nom du fichier
day=$2 # jour recherché
error="$3" # chaine erreur
#fic=/data/mysql/databases/pdtb2.err
#day=131222
#error="ERROR"
echo "File : $fic"
echo "day : $day"
echo "error : $error"
nbligne=`cat $fic | wc -l`
echo "nom de lignes dans le fichier log : " $nbligne
numligne=`grep -n "$day " $fic |head -1 | awk -F ':' '{print $1}'`
if [ "x$numligne" == "x" ]; then
 echo "Pas d erreur trouvée"
 exit 0
else
 echo "Erreur trouvée en ligne : " $numligne
fi
# on compte le nombre d'erreurs trouvées et on affiche les 5 lignes suivantes du log
cpt=`tail -n +$numligne $fic | grep -C 5 $error |wc -l`
if [ $cpt == 0 ]; then
 # si pas d'erreur on sort
 exit 0
else
 # On affiche les erreur pour le log Vtom
 tail -n +$numligne $fic | grep -C 5 $error
 exit $cpt
fi